Ok, I'm working on an iPhone project where I have to consider what is going on with the Squeak Drawing cycle. The original logic takes the ioShowDisplay(dispBitsIndex, w, h, d, left, right, top, bottom); and builds CGImageRefs from the dispBitsIndex data. This is an immutable object and actually uses Copy On Write Virtual Paging logic to ensure what the bits were when ioShowDisplay was called are what they will be when it's drawn. Usually ioShowDisplay is followed by a ForceDisplayUpdate which would then trigger the VM to take the queue of CGImageRefs (zero or more) and draw them to the screen. This entails invalidating the combined rectangle(s), and waiting for the video sync logic to catch up and render the CGImageRef(s) to the drawing surface. There is a case where if you use warpblt then showDisplayBitsLeftTopRightBottom is uses and doesn't do the ioForceDisplayUpdate. This is triggered by the primitive 231 code. However on both the Macintosh and iPhone I have a dead man's timer and fire the primitiveForceDisplayUpdate if a draw is pending and oh say about 20 millisecond passes. This ensure the queue doesn't go to infinity (I've a production example of that...) This works fine on os-x because we write to a window backing store but only flush the data to the window server for drawing based on the forceupdate. But on the iPhone it's different. We draw the CGImageRefs, BUT at some point the graphic layer can flush the content or part of the content and expect you to redraw eveything. However I don't have any of that information, or I didn't think I did, so I get black chunks of nothingness.... I've moved from something rather complex, tricky and broken on the iPhone to something more simple which makes a copy of all the drawing. But it's painfully slow. Last night I got to thinking, where *does* the data come from. So it appears and people can help confirm this, that Squeak *always* draws the data to the pointer in specialObjectsOops ->TheDisplay, found via sqInt displayObject(void). I recall that Tim had a hook for the ARM code to make the memory pointer not point to an area in Squeak OOps space, but to point it to video memory? Anyway I'm thinking here I should be able to at ForceDisplayUpdate time take the recorded rectangle data from ioShowDisplay and pull the bits directly from specialObjectsOops ->TheDisplay So anyone think this is not feasible? I'd also look at doing this on OS-X since it avoids building the intern CGImageRefs. ioShowDisplay displayBitsOfLeftTopRightBottom fullDisplayUpdate Platform usage, not used on mac. !ioForceDisplayUpdate! primitiveShowDisplayRect !ioForceDisplayUpdate! Primitive 127 Via DisplayScreen>>primShowRectLeft:right:top:bottom: Via DisplayScreen>>primRetryShowRectLeft:right:top:bottom: reverseDisplayFromto debugging code used by DoAssertionChecks !ioForceDisplayUpdate! showDisplayBitsLeftTopRightBottom **** only user of deferDisplayUpdates various places from BitBlt Plugin primitiveForceDisplayUpdate Primitive 231 sqInt displayObject(void) { return longAt((foo->specialObjectsOop + BaseHeaderSize) + (TheDisplay << ShiftForWord)); } -- =========================================================================== John M. McIntosh <[hidden email]> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com =========================================================================== |
Hi John, On Wed, Feb 10, 2010 at 11:28 AM, John M McIntosh <[hidden email]> wrote:
Cog does something similar to reference the native method associated with a bytecoded method. If a bytecoded method has been compiled to machine code by the JIT the its methodHeader word, which is usually a SmallInteger, gets replaced by the address of its machine code method's header. Each native method starts with a structure holding things like the saved methodHeader, the selector, how big it is, etc. To fool the garbage collector into thinking that the native method is an object that it doesn't need to worry about the first word of the header is the object header for a byte object with a compact class. Nothing more is needed because the native method zone is below the heap and so all references from bytecode method methodHeaders that refer to native methods look like objects below youngStart, and if you look at ObjectMemory>>markAndTrace: you'll see it doesn't mark old objects.
So if you want to create a remote frame buffer that looks like an object, the easy way, if possible, is to place the frame buffer below the heap, and put a word in front of it that contains the following value:
(16 << 12 "CompactClassIndex 16, or Bitmap") + HeaderTypeShort Then it'll look to the GC like a Bitmap object tat is always in oldSpace and so never to be mucked with.
Oh, but this will cause at: and at:put: to fail because it looks like a zero-length object. So instead you should use a three word header with the same compact class index and the right size value in the size field. Can't synthesize that off the top of my head, but you probably can. Please let me know what it is :)
HTH Eliot
|
In reply to this post by johnmci
Hi John - That's completely reasonable. If you check the Android VM, it basically does the same thing when updating the bits inside Java: http://code.google.com/p/squeak-android-vm/source/browse/trunk/project/jni/squeakvm.c int Java_org_squeak_android_SqueakVM_updateDisplay(JNIEnv *env, jobject self, jintArray bits, int w, int h, int d, int left, int top, int right, int bottom) { int row; sqInt formObj = interpreterProxy->displayObject(); sqInt formBits = interpreterProxy->fetchPointerofObject(0, formObj); sqInt width = interpreterProxy->fetchIntegerofObject(1, formObj); sqInt height = interpreterProxy->fetchIntegerofObject(2, formObj); sqInt depth = interpreterProxy->fetchIntegerofObject(3, formObj); int *dispBits = interpreterProxy->firstIndexableField(formBits); if(depth != 32) { dprintf(4, "updateDisplay: Display depth %d\n", depth); return 0; } if(width != w) { dprintf(4, "updateDisplay: Display width is %d (expected %d)\n", width, w); } if(height != h) { dprintf(4, "updateDisplay: Display width is %d (expected %d)\n", height, h); } for(row = top; row < bottom; row++) { int ofs = width*row+left; (*env)->SetIntArrayRegion(env, bits, ofs, right-left, dispBits+ofs); } return 1; } Cheers, - Andreas John M McIntosh wrote: > > Ok, I'm working on an iPhone project where I have to consider what is going on with the Squeak Drawing cycle. > The original logic takes the > > ioShowDisplay(dispBitsIndex, w, h, d, left, right, top, bottom); > > and builds CGImageRefs from the dispBitsIndex data. This is an immutable object and actually uses Copy On Write Virtual Paging logic > to ensure what the bits were when ioShowDisplay was called are what they will be when it's drawn. > > Usually ioShowDisplay is followed by a ForceDisplayUpdate which would then trigger the VM to take the queue of CGImageRefs (zero or more) and draw them to the screen. This entails invalidating the combined rectangle(s), and waiting for the video sync logic to catch up and render the CGImageRef(s) to the drawing surface. > > There is a case where if you use warpblt then showDisplayBitsLeftTopRightBottom is uses and doesn't do the ioForceDisplayUpdate. This is triggered by > the primitive 231 code. However on both the Macintosh and iPhone I have a dead man's timer and fire the primitiveForceDisplayUpdate if a draw is pending and > oh say about 20 millisecond passes. This ensure the queue doesn't go to infinity (I've a production example of that...) > > This works fine on os-x because we write to a window backing store but only flush the data to the window server for drawing based on the forceupdate. > > But on the iPhone it's different. > We draw the CGImageRefs, BUT at some point the graphic layer can flush the content or part of the content and expect you to redraw eveything. However I don't have any of that information, or I didn't think I did, so I get black chunks of nothingness.... > > I've moved from something rather complex, tricky and broken on the iPhone to something more simple which makes a copy of all the drawing. But it's painfully slow. > > Last night I got to thinking, where *does* the data come from. So it appears and people can help confirm this, that Squeak *always* draws the data to the pointer in specialObjectsOops ->TheDisplay, found via sqInt displayObject(void). > > I recall that Tim had a hook for the ARM code to make the memory pointer not point to an area in Squeak OOps space, but to point it to video memory? > > Anyway I'm thinking here I should be able to at ForceDisplayUpdate time take the recorded rectangle data from ioShowDisplay and pull the bits directly from > specialObjectsOops ->TheDisplay > > So anyone think this is not feasible? I'd also look at doing this on OS-X since it avoids building the intern CGImageRefs. > > > ioShowDisplay > displayBitsOfLeftTopRightBottom > > fullDisplayUpdate > Platform usage, not used on mac. > !ioForceDisplayUpdate! > > primitiveShowDisplayRect > !ioForceDisplayUpdate! > Primitive 127 > Via DisplayScreen>>primShowRectLeft:right:top:bottom: > Via DisplayScreen>>primRetryShowRectLeft:right:top:bottom: > > reverseDisplayFromto > debugging code used by DoAssertionChecks > !ioForceDisplayUpdate! > > showDisplayBitsLeftTopRightBottom > **** only user of deferDisplayUpdates > various places from BitBlt Plugin > > > primitiveForceDisplayUpdate > Primitive 231 > > > sqInt displayObject(void) { > return longAt((foo->specialObjectsOop + BaseHeaderSize) + (TheDisplay << ShiftForWord)); > } > > > > -- > =========================================================================== > John M. McIntosh <[hidden email]> Twitter: squeaker68882 > Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com > =========================================================================== > > > > |
Free forum by Nabble | Edit this page |