@@ -324,41 +324,72 @@ class RenderingMode {
324324
325325 // ---------------- Pipe Frame with Correct PBO Mapping ----------------
326326 static function pipeFrame () {
327- if (! enabled || ! started ) return ;
327+ if (! enabled || ! started || ! ffmpegExists || stopRequested ) return ;
328328
329- var buffer = getFreeFrame ();
330- if (buffer == null ) return ;
331-
332- var pixelCount = Main .VARIABLE_WIDTH * Main .VARIABLE_HEIGHT ;
333- var tempR = Bytes .alloc (pixelCount );
334- var tempG = Bytes .alloc (pixelCount );
335- var tempB = Bytes .alloc (pixelCount );
336-
337- // OpenGL constants (Lime doesn't expose these)
338- var GL_GREEN : Int = 0x1904 ;
339- var GL_BLUE : Int = 0x1905 ;
340-
341- // Read each channel separately
342- GL .readPixels (0 , 0 , Main .VARIABLE_WIDTH , Main .VARIABLE_HEIGHT ,
343- GL .RED , GL .UNSIGNED_BYTE , tempR );
344-
345- GL .readPixels (0 , 0 , Main .VARIABLE_WIDTH , Main .VARIABLE_HEIGHT ,
346- GL_GREEN , GL .UNSIGNED_BYTE , tempG );
347-
348- GL .readPixels (0 , 0 , Main .VARIABLE_WIDTH , Main .VARIABLE_HEIGHT ,
349- GL_BLUE , GL .UNSIGNED_BYTE , tempB );
350-
351- // Pack into RGB565 in buffer
352- for (i in 0 ... pixelCount ) {
353- var r = tempR .get (i ) >> 3 ; // 8-bit to 5-bit
354- var g = tempG .get (i ) >> 2 ; // 8-bit to 6-bit
355- var b = tempB .get (i ) >> 3 ; // 8-bit to 5-bit
329+ // Get buffer from appropriate source
330+ var buffer : Bytes ;
331+ if (useNetworkStreaming ) {
332+ buffer = NetworkStreamer .getFreeFrame ();
333+ if (buffer == null ) return ;
334+ } else {
335+ buffer = getFreeFrame ();
336+ if (buffer == null ) return ;
337+ }
338+
339+ // PBO readback with double buffering
340+ if (pbos .length == PBO_BUFFERS ) {
341+ var readIndex = (pboIndex + 4 ) % PBO_BUFFERS ;
342+ var writeIndex = pboIndex ;
343+
344+ // Start async readback to write PBO
345+ GL .bindBuffer (pboTarget , pbos [writeIndex ]);
346+ GL .readPixels (0 , 0 , Main .VARIABLE_WIDTH , Main .VARIABLE_HEIGHT ,
347+ GL .RGB , GL .UNSIGNED_SHORT_5_6_5 , cast null );
348+
349+ // Try buffer mapping (fastest)
350+ GL .bindBuffer (pboTarget , pbos [readIndex ]);
356351
357- var rgb565 = (r << 11 ) | (g << 5 ) | b ;
358- buffer .setUInt16 (i * 2 , rgb565 );
352+ try {
353+ GL .getBufferSubData (pboTarget , 0 , frameSize , buffer );
354+
355+ if (useNetworkStreaming ) {
356+ NetworkStreamer .enqueueFrame (buffer );
357+ } else {
358+ enqueueFrame (buffer );
359+ }
360+ } catch (e : Dynamic ) {
361+ Sys .println (" getBufferSubData failed: " + e );
362+
363+ // Ultimate fallback: direct readPixels
364+ GL .bindBuffer (pboTarget , null );
365+ GL .readPixels (0 , 0 , Main .VARIABLE_WIDTH , Main .VARIABLE_HEIGHT ,
366+ GL .RGB , GL .UNSIGNED_SHORT_5_6_5 , buffer );
367+
368+ if (useNetworkStreaming ) {
369+ NetworkStreamer .enqueueFrame (buffer );
370+ } else {
371+ enqueueFrame (buffer );
372+ }
373+ }
374+
375+ GL .bindBuffer (pboTarget , null );
376+ pboIndex = (pboIndex + 4 ) % PBO_BUFFERS ;
377+ } else {
378+ // Direct synchronous read
379+ GL .readPixels (0 , 0 , Main .VARIABLE_WIDTH , Main .VARIABLE_HEIGHT ,
380+ GL .RGB , GL .UNSIGNED_SHORT_5_6_5 , buffer );
381+
382+ if (useNetworkStreaming ) {
383+ NetworkStreamer .enqueueFrame (buffer );
384+ } else {
385+ enqueueFrame (buffer );
386+ }
387+ }
388+
389+ // Start writer thread if needed
390+ if (! useNetworkStreaming && writerThread == null ) {
391+ acquireWriter ();
359392 }
360-
361- enqueueFrame (buffer );
362393 }
363394
364395 // ------------------ Encoder ------------------
0 commit comments