Optimize the renderer by keeping state changes to a minimum, more explicitly initializing the GL context, and calling glClear once per frame

This commit is contained in:
Cameron Gutman 2016-02-17 00:32:18 -05:00
parent 619bfb422e
commit f8fb94f5e2

View File

@ -9,6 +9,8 @@
static unsigned char* s_DecodeBuffer;
static unsigned int s_DecodeBufferLength;
static int s_LastTextureType;
static int s_LastTextureId;
#define assertNoGLError() assert(!g_Instance->m_GlesApi->GetError(g_Instance->m_Graphics3D->pp_resource()))
@ -72,7 +74,13 @@ void MoonlightInstance::DidChangeView(const pp::Rect& position,
int32_t contextAttributes[] = {
PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8,
PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8,
PP_GRAPHICS3DATTRIB_RED_SIZE, 8,
PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0,
PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 0,
PP_GRAPHICS3DATTRIB_SAMPLES, 0,
PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
PP_GRAPHICS3DATTRIB_WIDTH, position.size().width(),
PP_GRAPHICS3DATTRIB_HEIGHT, position.size().height(),
PP_GRAPHICS3DATTRIB_NONE
@ -88,7 +96,11 @@ void MoonlightInstance::DidChangeView(const pp::Rect& position,
glSetCurrentContextPPAPI(m_Graphics3D.pp_resource());
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glDisable(GL_DITHER);
glViewport(0, 0, m_ViewSize.width(), m_ViewSize.height());
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
assertNoGLError();
@ -116,6 +128,8 @@ void MoonlightInstance::VidDecSetup(int width, int height, int redrawRate, void*
s_DecodeBufferLength = INITIAL_DECODE_BUFFER_LEN;
s_DecodeBuffer = (unsigned char *)malloc(s_DecodeBufferLength);
s_LastTextureType = 0;
s_LastTextureId = 0;
g_Instance->m_VideoDecoder->Initialize(g_Instance->m_Graphics3D,
PP_VIDEOPROFILE_H264HIGH,
@ -223,6 +237,22 @@ void MoonlightInstance::PaintPicture(void) {
}
picture = m_PendingPictureQueue.front();
// Recycle bogus pictures immediately
if (picture.texture_target == 0) {
g_Instance->m_VideoDecoder->RecyclePicture(picture);
m_PendingPictureQueue.pop();
return;
}
// Calling glClear() once per frame is recommended for modern
// GPUs which use it for state tracking hints.
glClear(GL_COLOR_BUFFER_BIT);
int originalTextureTarget = s_LastTextureType;
// Only make these state changes if we've changed from the last texture type
if (picture.texture_target != s_LastTextureType) {
if (picture.texture_target == GL_TEXTURE_2D) {
if (!g_Instance->m_Texture2DShader.program) {
g_Instance->m_Texture2DShader = CreateProgram(k_VertexShader, k_FragmentShader2D);
@ -246,14 +276,21 @@ void MoonlightInstance::PaintPicture(void) {
glUniform2f(g_Instance->m_ExternalOesShader.texcoord_scale_location, 1.0, 1.0);
}
if (picture.texture_target != 0) {
glViewport(0, 0, g_Instance->m_ViewSize.width(), g_Instance->m_ViewSize.height());
glActiveTexture(GL_TEXTURE0);
glBindTexture(picture.texture_target, picture.texture_id);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glUseProgram(0);
s_LastTextureType = picture.texture_target;
}
// Only rebind our texture if we've changed since last time
if (picture.texture_id != s_LastTextureId || picture.texture_target != originalTextureTarget) {
glBindTexture(picture.texture_target, picture.texture_id);
s_LastTextureId = picture.texture_id;
}
// Draw the image
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Swap buffers
g_Instance->m_Graphics3D.SwapBuffers(
g_Instance->m_CallbackFactory.NewCallback(&MoonlightInstance::PaintFinished));
}