Index: gpu/command_buffer/service/gles2_cmd_decoder.cc |
=================================================================== |
--- gpu/command_buffer/service/gles2_cmd_decoder.cc (revision 49195) |
+++ gpu/command_buffer/service/gles2_cmd_decoder.cc (working copy) |
@@ -13,6 +13,7 @@ |
#include <vector> |
#include "app/gfx/gl/gl_context.h" |
+#include "app/gfx/gl/gl_implementation.h" |
#include "base/callback.h" |
#include "base/scoped_ptr.h" |
#include "base/weak_ptr.h" |
@@ -246,9 +247,9 @@ |
// Attach a color render buffer to a frame buffer. |
void AttachRenderTexture(Texture* texture); |
- // Attach a depth stencil render buffer to a frame buffer. Note that |
- // this unbinds any currently bound frame buffer. |
- void AttachDepthStencilRenderBuffer(RenderBuffer* render_buffer); |
+ // Attach a render buffer to a frame buffer. Note that this unbinds any |
+ // currently bound frame buffer. |
+ void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer); |
// Clear the given attached buffers. |
void Clear(GLbitfield buffers); |
@@ -1126,10 +1127,14 @@ |
bool anti_aliased_; |
- // The offscreen frame buffer that the client renders to. |
+ // The offscreen frame buffer that the client renders to. With EGL, the |
+ // depth and stencil buffers are separate. With regular GL there is a single |
+ // packed depth stencil buffer in offscreen_target_depth_render_buffer_. |
+ // offscreen_target_stencil_render_buffer_ is unused. |
scoped_ptr<FrameBuffer> offscreen_target_frame_buffer_; |
scoped_ptr<Texture> offscreen_target_color_texture_; |
- scoped_ptr<RenderBuffer> offscreen_target_depth_stencil_render_buffer_; |
+ scoped_ptr<RenderBuffer> offscreen_target_depth_render_buffer_; |
+ scoped_ptr<RenderBuffer> offscreen_target_stencil_render_buffer_; |
// The copy that is saved when SwapBuffers is called. |
scoped_ptr<Texture> offscreen_saved_color_texture_; |
@@ -1249,7 +1254,6 @@ |
GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
- glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); |
glTexImage2D(GL_TEXTURE_2D, |
0, // mip level |
@@ -1353,19 +1357,16 @@ |
0); |
} |
-void FrameBuffer::AttachDepthStencilRenderBuffer(RenderBuffer* render_buffer) { |
+void FrameBuffer::AttachRenderBuffer(GLenum target, |
+ RenderBuffer* render_buffer) { |
DCHECK_NE(id_, 0u); |
ScopedGLErrorSuppressor suppressor(decoder_); |
ScopedFrameBufferBinder binder(decoder_, id_); |
GLuint attach_id = render_buffer ? render_buffer->id() : 0; |
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, |
- GL_DEPTH_ATTACHMENT, |
+ target, |
GL_RENDERBUFFER, |
attach_id); |
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, |
- GL_STENCIL_ATTACHMENT, |
- GL_RENDERBUFFER, |
- attach_id); |
} |
void FrameBuffer::Clear(GLbitfield buffers) { |
@@ -1411,6 +1412,16 @@ |
attrib_0_value_.v[1] = 0.0f; |
attrib_0_value_.v[2] = 0.0f; |
attrib_0_value_.v[3] = 1.0f; |
+ |
+ // The shader translator is not needed for EGL because it already uses the |
+ // GLSL ES syntax. It is translated for the unit tests because |
+ // GLES2DecoderWithShaderTest.GetShaderInfoLogValidArgs passes the empty |
+ // string to CompileShader and this is not a valid shader. TODO(apatrick): |
+ // fix this test. |
+ if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 || |
+ gfx::GetGLImplementation() == gfx::kGLImplementationMockGL) { |
+ use_shader_translator_ = false; |
+ } |
} |
bool GLES2DecoderImpl::Initialize(gfx::GLContext* context, |
@@ -1423,8 +1434,7 @@ |
// Create a GL context that is kept in a default state and shares a namespace |
// with the main GL context. |
- default_context_.reset(gfx::GLContext::CreateOffscreenGLContext( |
- context_->GetHandle())); |
+ default_context_.reset(gfx::GLContext::CreateOffscreenGLContext(context_)); |
if (!default_context_.get()) { |
Destroy(); |
return false; |
@@ -1483,7 +1493,6 @@ |
glBindTexture(GL_TEXTURE_CUBE_MAP, 0); |
CHECK_GL_ERROR(); |
-#if !defined(UNIT_TEST) |
if (context_->IsOffscreen()) { |
// Create the target frame buffer. This is the one that the client renders |
// directly to. |
@@ -1491,9 +1500,12 @@ |
offscreen_target_frame_buffer_->Create(); |
offscreen_target_color_texture_.reset(new Texture(this)); |
offscreen_target_color_texture_->Create(); |
- offscreen_target_depth_stencil_render_buffer_.reset( |
+ offscreen_target_depth_render_buffer_.reset( |
new RenderBuffer(this)); |
- offscreen_target_depth_stencil_render_buffer_->Create(); |
+ offscreen_target_depth_render_buffer_->Create(); |
+ offscreen_target_stencil_render_buffer_.reset( |
+ new RenderBuffer(this)); |
+ offscreen_target_stencil_render_buffer_->Create(); |
// Create the saved offscreen texture. The target frame buffer is copied |
// here when SwapBuffers is called. |
@@ -1522,24 +1534,27 @@ |
// This should now be associated with ID zero. |
DoBindFramebuffer(GL_FRAMEBUFFER, 0); |
} |
-#endif // UNIT_TEST |
-#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) |
// OpenGL ES 2.0 implicitly enables the desktop GL capability |
// VERTEX_PROGRAM_POINT_SIZE and doesn't expose this enum. This fact |
// isn't well documented; it was discovered in the Khronos OpenGL ES |
// mailing list archives. |
- glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); |
+ if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { |
+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); |
+ } |
-#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER) && !defined(UNIT_TEST) |
+#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER) |
// Initialize GLSL ES to GLSL translator. |
- if (!ShInitialize()) { |
- DLOG(ERROR) << "Could not initialize GLSL translator."; |
- Destroy(); |
- return false; |
+ static bool glsl_translator_initialized = false; |
+ if (!glsl_translator_initialized) { |
+ if (!ShInitialize()) { |
+ DLOG(ERROR) << "Could not initialize GLSL translator."; |
+ Destroy(); |
+ return false; |
+ } |
+ glsl_translator_initialized = true; |
} |
#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER |
-#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2 |
return true; |
} |
@@ -1655,11 +1670,7 @@ |
// } // anonymous namespace |
bool GLES2DecoderImpl::MakeCurrent() { |
-#if defined(UNIT_TEST) |
- return true; |
-#else |
return context_->MakeCurrent(); |
-#endif |
} |
gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() { |
@@ -1738,11 +1749,7 @@ |
} else if (offscreen_target_color_texture_.get()) { |
return offscreen_target_color_texture_->size(); |
} else { |
-#if defined(UNIT_TEST) |
- return gfx::Size(INT_MAX, INT_MAX); |
-#else |
return context_->GetSize(); |
-#endif |
} |
} |
@@ -1763,20 +1770,19 @@ |
return false; |
} |
-#if !defined(UNIT_TEST) |
+ // TODO(apatrick): Fix this once ANGLE supports shared contexts. |
// Clear the saved offscreen color texture. Use default GL context |
// to ensure clear is not affected by client set state. |
- { // NOLINT |
+ if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { |
ScopedDefaultGLContext scoped_context(this); |
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, |
+ glBindFramebufferEXT(GL_FRAMEBUFFER, |
offscreen_target_frame_buffer_->id()); |
glClear(GL_COLOR_BUFFER_BIT); |
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
+ glBindFramebufferEXT(GL_FRAMEBUFFER, 0); |
if (glGetError() != GL_NO_ERROR) |
return false; |
} |
-#endif |
} |
// Reallocate the offscreen target buffers. |
@@ -1785,35 +1791,60 @@ |
return false; |
} |
- if (!offscreen_target_depth_stencil_render_buffer_->AllocateStorage( |
- pending_offscreen_size_, GL_DEPTH24_STENCIL8)) { |
- return false; |
+ if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) { |
+ // ANGLE only allows 16-bit depth buffers to be requested. As it happens, |
+ // it creates a 24-bit depth buffer behind the scenes. |
+ // TODO(apatrick): Attempt to use a packed 24/8 depth stencil buffer here if |
+ // the extension is available. |
+ if (!offscreen_target_depth_render_buffer_->AllocateStorage( |
+ pending_offscreen_size_, GL_DEPTH_COMPONENT16)) { |
+ return false; |
+ } |
+ |
+ if (!offscreen_target_stencil_render_buffer_->AllocateStorage( |
+ pending_offscreen_size_, GL_STENCIL_INDEX8)) { |
+ return false; |
+ } |
+ } else { |
+ if (!offscreen_target_depth_render_buffer_->AllocateStorage( |
+ pending_offscreen_size_, GL_DEPTH24_STENCIL8)) { |
+ return false; |
+ } |
} |
// Attach the offscreen target buffers to the target frame buffer. |
offscreen_target_frame_buffer_->AttachRenderTexture( |
offscreen_target_color_texture_.get()); |
- offscreen_target_frame_buffer_->AttachDepthStencilRenderBuffer( |
- offscreen_target_depth_stencil_render_buffer_.get()); |
+ offscreen_target_frame_buffer_->AttachRenderBuffer( |
+ GL_DEPTH_ATTACHMENT, |
+ offscreen_target_depth_render_buffer_.get()); |
+ if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) { |
+ offscreen_target_frame_buffer_->AttachRenderBuffer( |
+ GL_STENCIL_ATTACHMENT, |
+ offscreen_target_stencil_render_buffer_.get()); |
+ } else { |
+ offscreen_target_frame_buffer_->AttachRenderBuffer( |
+ GL_STENCIL_ATTACHMENT, |
+ offscreen_target_depth_render_buffer_.get()); |
+ } |
if (offscreen_target_frame_buffer_->CheckStatus() != |
GL_FRAMEBUFFER_COMPLETE) { |
return false; |
} |
-#if !defined(UNIT_TEST) |
+ // TODO(apatrick): Fix this once ANGLE supports shared contexts. |
// Clear offscreen frame buffer to its initial state. Use default GL context |
// to ensure clear is not affected by client set state. |
- { // NOLINT |
+ if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { |
ScopedDefaultGLContext scoped_context(this); |
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, |
+ glBindFramebufferEXT(GL_FRAMEBUFFER, |
offscreen_target_frame_buffer_->id()); |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
+ glBindFramebufferEXT(GL_FRAMEBUFFER, 0); |
if (glGetError() != GL_NO_ERROR) |
return false; |
} |
-#endif |
if (parent_) { |
// Create the saved offscreen color texture (only accessible to parent). |
@@ -1885,11 +1916,16 @@ |
offscreen_target_color_texture_.reset(); |
} |
- if (offscreen_target_depth_stencil_render_buffer_.get()) { |
- offscreen_target_depth_stencil_render_buffer_->Destroy(); |
- offscreen_target_depth_stencil_render_buffer_.reset(); |
+ if (offscreen_target_depth_render_buffer_.get()) { |
+ offscreen_target_depth_render_buffer_->Destroy(); |
+ offscreen_target_depth_render_buffer_.reset(); |
} |
+ if (offscreen_target_stencil_render_buffer_.get()) { |
+ offscreen_target_stencil_render_buffer_->Destroy(); |
+ offscreen_target_stencil_render_buffer_.reset(); |
+ } |
+ |
if (offscreen_saved_color_texture_.get()) { |
offscreen_saved_color_texture_->Destroy(); |
offscreen_saved_color_texture_.reset(); |
@@ -1900,13 +1936,6 @@ |
default_context_->Destroy(); |
default_context_.reset(); |
} |
- |
-#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) && !defined(UNIT_TEST) |
-#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER) |
- // Terminate GLSL translator. |
- ShFinalize(); |
-#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER |
-#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2 |
} |
void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) { |
@@ -2176,8 +2205,8 @@ |
bool GLES2DecoderImpl::GetHelper( |
GLenum pname, GLint* params, GLsizei* num_written) { |
DCHECK(num_written); |
- switch (pname) { |
-#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) |
+ if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { |
+ switch (pname) { |
case GL_IMPLEMENTATION_COLOR_READ_FORMAT: |
*num_written = 1; |
if (params) { |
@@ -2208,7 +2237,9 @@ |
*params = group_->max_vertex_uniform_vectors(); |
} |
return true; |
-#endif |
+ } |
+ } |
+ switch (pname) { |
case GL_COMPRESSED_TEXTURE_FORMATS: |
*num_written = 0; |
// We don't support compressed textures. |
@@ -3232,7 +3263,6 @@ |
// Translate GL ES 2.0 shader to Desktop GL shader and pass that to |
// glShaderSource and then glCompileShader. |
const char* shader_src = info->source().c_str(); |
-#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) && !defined(UNIT_TEST) |
#if defined(GLES2_GPU_SERVICE_TRANSLATE_SHADER) |
ShHandle compiler = 0; |
if (use_shader_translator_) { |
@@ -3258,21 +3288,19 @@ |
ShDestruct(compiler); |
return; |
} |
+ |
info->SetTranslationStatus(true, ""); |
shader_src = ShGetObjectCode(compiler); |
} |
#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER |
-#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2 |
glShaderSource(info->service_id(), 1, &shader_src, NULL); |
glCompileShader(info->service_id()); |
-#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) && !defined(UNIT_TEST) |
#ifdef GLES2_GPU_SERVICE_TRANSLATE_SHADER |
if (use_shader_translator_) { |
ShDestruct(compiler); |
} |
#endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER |
-#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2 |
}; |
void GLES2DecoderImpl::DoGetShaderiv( |
@@ -4009,7 +4037,7 @@ |
} |
void GLES2DecoderImpl::DoBufferData( |
- GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) { |
+ GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) { |
if (!ValidateGLenumBufferTarget(target)) { |
SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM"); |
return; |
@@ -4674,9 +4702,7 @@ |
offscreen_saved_color_texture_->Copy( |
offscreen_saved_color_texture_->size()); |
} else { |
-#if !defined(UNIT_TEST) |
context_->SwapBuffers(); |
-#endif |
} |
// TODO(kbr): when the back buffer is multisampled, then at least on Mac |