Chromium Code Reviews| Index: gpu/command_buffer/service/gles2_cmd_decoder.cc |
| diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| index c480b71567dca3814c19aeca0b4f7185bc338e42..eeee706c51c834c111fed9093c0c1f7f88314883 100644 |
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| @@ -65,6 +65,7 @@ |
| #include "gpu/command_buffer/service/transform_feedback_manager.h" |
| #include "gpu/command_buffer/service/vertex_array_manager.h" |
| #include "gpu/command_buffer/service/vertex_attrib_manager.h" |
| +#include "gpu/ipc/common/gpu_surface_lookup.h" |
|
piman
2016/11/09 17:50:07
So, including gpu/ipc is a layering violation. Ind
klausw
2016/11/11 00:04:10
I'm a bit confused about the layering violation an
|
| #include "third_party/angle/src/image_util/loadimage.h" |
| #include "third_party/smhasher/src/City.h" |
| #include "ui/gfx/buffer_types.h" |
| @@ -82,6 +83,7 @@ |
| #include "ui/gl/gl_image.h" |
| #include "ui/gl/gl_implementation.h" |
| #include "ui/gl/gl_surface.h" |
| +#include "ui/gl/gl_surface_egl.h" |
|
piman
2016/11/09 17:50:06
I believe we can't include this on Mac (EGL is not
klausw
2016/11/09 21:21:55
Done, now Android only.
|
| #include "ui/gl/gl_version_info.h" |
| #include "ui/gl/gpu_timing.h" |
| @@ -1034,6 +1036,8 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
| void DoFlushMappedBufferRange( |
| GLenum target, GLintptr offset, GLsizeiptr size); |
| + void DoSetSurfaceHandleCHROMIUM(GLint surface_handle); |
| + |
| // Creates a Program for the given program. |
| Program* CreateProgram(GLuint client_id, GLuint service_id) { |
| return program_manager()->CreateProgram(client_id, service_id); |
| @@ -2131,6 +2135,17 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
| scoped_refptr<gl::GLSurface> surface_; |
| scoped_refptr<gl::GLContext> context_; |
| + // Direct render mode data for switching and restoring the |
| + // underlying destination surface, cf. DoSetSurfaceHandleCHROMIUM. |
| + struct DirectRenderState{ |
| + scoped_refptr<gl::GLSurface> direct_surface; |
| + scoped_refptr<gl::GLSurface> orig_surface; |
| + std::unique_ptr<BackFramebuffer> orig_offscreen_target_frame_buffer; |
| + bool orig_supports_async_swap; |
| + bool orig_back_buffer_has_depth; |
|
piman
2016/11/09 17:50:07
saving/restoring the old values seems like additio
klausw
2016/11/09 21:21:56
I've refactored it by extracting bits of Initializ
|
| + }; |
| + std::unique_ptr<DirectRenderState> direct_render_state_; |
| + |
| // The ContextGroup for this decoder uses to track resources. |
| scoped_refptr<ContextGroup> group_; |
| @@ -16937,6 +16952,85 @@ void GLES2DecoderImpl::DoApplyScreenSpaceAntialiasingCHROMIUM() { |
| } |
| } |
| +void GLES2DecoderImpl::DoSetSurfaceHandleCHROMIUM(GLint surface_handle) { |
| +#if defined(OS_ANDROID) |
| + if (surface_handle) { |
| + // Use the specified surface as a render target, and save decoder |
| + // state so that this can be reverted later. |
| + |
| + // Ignore redundant calls. For now we don't support switching between |
| + // different surfaces, if you need this you have to make a call with |
| + // surface_handle=0 in between. |
|
piman
2016/11/09 17:50:06
This is a bit distasteful as an API... It doesn't
klausw
2016/11/09 21:21:55
Fixed, it raises an error now if the current conte
|
| + if (direct_render_state_) { |
| + return; |
| + } |
| + |
| + direct_render_state_.reset(new DirectRenderState()); |
| + |
| + // One-time initialization when first activating a direct draw surface. |
| + ANativeWindow* window = |
| + gpu::GpuSurfaceLookup::GetInstance()->AcquireNativeWidget( |
| + surface_handle); |
|
piman
2016/11/09 17:50:06
This could be NULL? How should we handle this?
klausw
2016/11/09 21:21:55
Changed to raise an error.
|
| + direct_render_state_->direct_surface = |
| + new gl::NativeViewGLSurfaceEGL(window); |
|
piman
2016/11/09 17:50:07
So, this is an extremely powerful capability. If t
klausw
2016/11/11 00:04:10
After discussion with Brandon, it sounds best to g
|
| + |
| + // It would be useful if we could get a custom surface format such |
| + // as one with a depth buffer here, but the new surface must use |
| + // the same format as the one originally used for creating the GL |
| + // context. Anything else just results in BAD_MATCH errors. |
| + bool initialize_success = direct_render_state_->direct_surface->Initialize( |
| + surface_->GetFormat()); |
| + if (!initialize_success) { |
| + LOG(ERROR) << "Direct render surface init failed for handle " << |
| + surface_handle; |
| + } |
| + ANativeWindow_release(window); |
| + |
| + direct_render_state_->orig_surface = surface_; |
| + |
| + // We don't want async swap since we want full control over when the |
| + // SurfaceTexture gets updated. |
|
piman
2016/11/09 17:50:06
FYI, "async" swap doesn't remove any "control", it
klausw
2016/11/09 21:21:55
I removed this, I had misunderstood how it works a
|
| + direct_render_state_->orig_supports_async_swap = supports_async_swap_; |
| + supports_async_swap_ = false; |
|
piman
2016/11/09 17:50:06
what about other properties of the surface, like s
klausw
2016/11/09 21:21:55
See above, the new shared methods should keep them
|
| + direct_render_state_->orig_back_buffer_has_depth = back_buffer_has_depth_; |
| + back_buffer_has_depth_ = true; |
|
piman
2016/11/09 17:50:06
What makes this true?
klausw
2016/11/09 21:21:55
This was an assumption based on the current use ca
|
| + // override back_buffer_has_stencil_ too? |
|
piman
2016/11/09 17:50:07
What is this comment, is it a TODO? If so, please
klausw
2016/11/09 21:21:55
Should be fixed now.
|
| + |
| + // Offscreen surfaces don't support SwapBuffers, make sure it's not |
| + // considered offscreen. Various code in this file checks for is_offscreen |
| + // = !!offscreen_target_frame_buffer_.get(). |
| + direct_render_state_->orig_offscreen_target_frame_buffer = |
| + std::move(offscreen_target_frame_buffer_); |
| + offscreen_target_frame_buffer_.reset(nullptr); |
| + |
| + // Activate the surface. This does *not* rebind the active framebuffer, |
| + // callers must do so themselves as needed. |
|
piman
2016/11/09 17:50:06
We should keep a consistent state. If the default
klausw
2016/11/09 21:21:55
I've added MakeCurrent and am applying glViewport
piman
2016/11/09 22:26:09
Correct.
klausw
2016/11/10 02:28:07
Acknowledged.
|
| + SetSurface(direct_render_state_->direct_surface); |
| + } else { |
| + // Restore original state for drawing offscreen. |
| + |
| + // Ignore redundant calls. |
| + if (!direct_render_state_) return; |
| + |
| + supports_async_swap_ = direct_render_state_->orig_supports_async_swap; |
| + back_buffer_has_depth_ = direct_render_state_->orig_back_buffer_has_depth; |
| + offscreen_target_frame_buffer_ = |
| + std::move(direct_render_state_->orig_offscreen_target_frame_buffer); |
| + |
| + SetSurface(direct_render_state_->orig_surface); |
| + |
| + // Trust the state struct's destructors to handle refcounting for |
| + // surfaces and trigger apprpriate cleanup. |
| + direct_render_state_.reset(); |
| + } |
| +#else // !OS_ANDROID |
| + LOCAL_SET_GL_ERROR( |
| + GL_INVALID_OPERATION, |
| + "glSetSurfaceHandleCHROMIUM", |
| + "Direct render surface is unsupported on this platform"); |
| +#endif |
| +} |
| + |
| void GLES2DecoderImpl::DoInsertEventMarkerEXT( |
| GLsizei length, const GLchar* marker) { |
| if (!marker) { |