static WarpProgram BuildWarpProg( const char * vertex, const char * fragment ) { WarpProgram wp; WarpProgram_Create( &wp, vertex, fragment ); return wp; }
// Called by TimeWarp before adding the KHR sync object. void ImageServer::EnterWarpSwap( int eyeTexture ) { ImageServerRequest request = Request.GetState(); if ( request.Sequence <= SequenceCaptured ) { return; } SequenceCaptured = request.Sequence; // create GL objects if necessary if ( !ResampleProg.program ) { WarpProgram_Create( &ResampleProg, "uniform highp mat4 Mvpm;\n" "attribute vec4 Position;\n" "attribute vec2 TexCoord;\n" "varying highp vec2 oTexCoord;\n" "void main()\n" "{\n" " gl_Position = Position;\n" " oTexCoord = vec2( TexCoord.x, 1.0 - TexCoord.y );\n" // need to flip Y "}\n" , "uniform sampler2D Texture0;\n" "varying highp vec2 oTexCoord;\n" "void main()\n" "{\n" " gl_FragColor = texture2D( Texture0, oTexCoord );\n" "}\n" ); } if ( !Quad.vertexArrayObject ) { WarpGeometry_CreateQuad( &Quad ); } // If resolution has changed, delete and reallocate the buffers // These might still be in use, do we trust the driver or try to // deal with it ourselves? if ( request.Resolution != CurrentResolution ) { CurrentResolution = request.Resolution; FreeBuffers(); } // Allocate any resources we need if ( !ResampleRenderBuffer ) { LOG( "Alloc %i res renderbuffer", CurrentResolution ); glGenRenderbuffers( 1, &ResampleRenderBuffer ); glBindRenderbuffer( GL_RENDERBUFFER, ResampleRenderBuffer ); glRenderbufferStorage( GL_RENDERBUFFER, GL_RGB565, CurrentResolution, CurrentResolution ); } if ( !FrameBufferObject ) { LOG( "Alloc FrameBufferObject" ); glGenFramebuffers( 1, &FrameBufferObject ); glBindFramebuffer( GL_FRAMEBUFFER, FrameBufferObject ); glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ResampleRenderBuffer ); const GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER ); if (status != GL_FRAMEBUFFER_COMPLETE ) { LOG( "FBO is not complete: 0x%x", status ); } } if ( !PixelBufferObject ) { LOG( "Alloc PixelBufferObject" ); glGenBuffers( 1, &PixelBufferObject ); glBindBuffer( GL_PIXEL_PACK_BUFFER, PixelBufferObject ); glBufferData( GL_PIXEL_PACK_BUFFER, CurrentResolution*CurrentResolution*2, NULL, GL_DYNAMIC_READ ); glBindBuffer( GL_PIXEL_PACK_BUFFER, 0 ); } // Render the FBO glBindFramebuffer( GL_FRAMEBUFFER, FrameBufferObject ); glDisable( GL_DEPTH_TEST ); glDisable( GL_SCISSOR_TEST ); GL_InvalidateFramebuffer( INV_FBO, true, false ); glViewport( 0, 0, CurrentResolution, CurrentResolution ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, eyeTexture ); glUseProgram( ResampleProg.program ); glBindVertexArrayOES_( Quad.vertexArrayObject ); glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL ); glBindVertexArrayOES_( 0 ); glUseProgram( 0 ); // unmap the previous PBO mapping if ( PboMappedAddress ) { glBindBuffer( GL_PIXEL_PACK_BUFFER, PixelBufferObject ); glUnmapBuffer_( GL_PIXEL_PACK_BUFFER ); glBindBuffer( GL_PIXEL_PACK_BUFFER, 0 ); PboMappedAddress = NULL; } // Issue an async read into our PBO #if 1 glBindBuffer( GL_PIXEL_PACK_BUFFER, PixelBufferObject ); glReadPixels( 0, 0, CurrentResolution, CurrentResolution, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0 ); // back to normal memory read operations glBindBuffer( GL_PIXEL_PACK_BUFFER, 0 ); #else GL_CheckErrors( "before read" ); static short pixels[256*256]; glReadPixels( 0, 0, CurrentResolution, CurrentResolution, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (GLvoid *)pixels ); ImageServerResponse response; response.Data = (void *)pixels; response.Resolution = CurrentResolution; response.Sequence = request.Sequence; Response.SetState( response ); #endif glBindFramebuffer( GL_FRAMEBUFFER, 0 ); GL_CheckErrors( "after read" ); CountdownToSend = 2; }