diff options
Diffstat (limited to 'gpu/command_buffer/service/gles2_cmd_decoder.cc')
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 803 |
1 files changed, 146 insertions, 657 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 32308a5..4f70ecf 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -10,11 +10,11 @@ #include <vector> #include <string> #include <map> -#include <build/build_config.h> // NOLINT #include "base/callback.h" #include "base/linked_ptr.h" #include "base/scoped_ptr.h" #include "base/weak_ptr.h" +#include "build/build_config.h" #define GLES2_GPU_SERVICE 1 #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" @@ -22,6 +22,7 @@ #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/framebuffer_manager.h" +#include "gpu/command_buffer/service/gl_context.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/gles2_cmd_validation.h" #include "gpu/command_buffer/service/id_manager.h" @@ -29,13 +30,6 @@ #include "gpu/command_buffer/service/renderbuffer_manager.h" #include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/texture_manager.h" -#if defined(UNIT_TEST) -#elif defined(OS_LINUX) -// GLXContextWrapper is stubbed out for unit-tests. -#include "gpu/command_buffer/service/x_utils.h" -#elif defined(OS_MACOSX) -#include "app/surface/accelerated_surface_mac.h" -#endif #if !defined(GL_DEPTH24_STENCIL8) #define GL_DEPTH24_STENCIL8 0x88F0 @@ -185,9 +179,14 @@ class Texture { return id_; } + gfx::Size size() const { + return size_; + } + private: GLES2DecoderImpl* decoder_; GLuint id_; + gfx::Size size_; DISALLOW_COPY_AND_ASSIGN(Texture); }; @@ -256,17 +255,7 @@ class FrameBuffer { GLES2Decoder::GLES2Decoder(ContextGroup* group) : group_(group), -#if defined(UNIT_TEST) debug_(false) { -#elif defined(OS_LINUX) - debug_(false), - context_(NULL) { -#elif defined(OS_WIN) - debug_(false), - hwnd_(NULL) { -#else - debug_(false) { -#endif } GLES2Decoder::~GLES2Decoder() { @@ -356,34 +345,16 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, virtual const char* GetCommandName(unsigned int command_id) const; // Overridden from GLES2Decoder. - virtual bool Initialize(GLES2Decoder* parent, + virtual bool Initialize(GLContext* context, const gfx::Size& size, + GLES2Decoder* parent, uint32 parent_client_texture_id); virtual void Destroy(); virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size); virtual bool MakeCurrent(); virtual uint32 GetServiceIdForTesting(uint32 client_id); virtual GLES2Util* GetGLES2Util() { return &util_; } - -#if defined(OS_MACOSX) - // Overridden from GLES2Decoder. - - // The recommended usage is to call SetWindowSizeForIOSurface() first, and if - // that returns 0, try calling SetWindowSizeForTransportDIB(). A return value - // of 0 from SetWindowSizeForIOSurface() might mean the IOSurface API is not - // available, which is true if you are not running on Max OS X 10.6 or later. - // If SetWindowSizeForTransportDIB() also returns a NULL handle, then an - // error has occured. - virtual uint64 SetWindowSizeForIOSurface(int32 width, int32 height); - virtual TransportDIB::Handle SetWindowSizeForTransportDIB(int32 width, - int32 height); - // |allocator| sends a message to the renderer asking for a new - // TransportDIB big enough to hold the rendered bits. The parameters to the - // call back are the size of the DIB and the handle (filled in on return). - virtual void SetTransportDIBAllocAndFree( - Callback2<size_t, TransportDIB::Handle*>::Type* allocator, - Callback1<TransportDIB::Id>::Type* deallocator); -#endif + virtual GLContext* GetGLContext() { return context_; } virtual void SetSwapBuffersCallback(Callback0::Type* callback); @@ -456,15 +427,6 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, return group_->texture_manager(); } -#if defined(OS_WIN) - static bool InitializeOneOff(bool anti_aliased); -#endif - - - bool InitPlatformSpecific(); - static bool InitGlew(); - void DestroyPlatformSpecific(); - bool UpdateOffscreenFrameBufferSize(); // Template to help call glGenXXX functions. @@ -517,6 +479,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, texture_manager()->RemoveTextureInfo(texture); } + // Get the size (in pixels) of the currently bound frame buffer (either FBO + // or regular back buffer). + gfx::Size GetBoundFrameBufferSize(); + // Wrapper for CompressedTexImage2D commands. error::Error DoCompressedTexImage2D( GLenum target, @@ -813,16 +779,16 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, #undef GLES2_CMD_OP + // The GL context this decoder renders to. + GLContext* context_; + // A parent decoder can access this decoders saved offscreen frame buffer. // The parent pointer is reset if the parent is destroyed. base::WeakPtr<GLES2DecoderImpl> parent_; // Width and height to which an offscreen frame buffer should be resized on // the next call to SwapBuffers. - gfx::Size pending_size_; - - // Width and height of a decoder that renders to an offscreen frame buffer. - gfx::Size current_size_; + gfx::Size pending_offscreen_size_; // Current GL error bits. uint32 error_bits_; @@ -871,19 +837,6 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // The currently bound renderbuffer GLuint bound_renderbuffer_; -#if defined(UNIT_TEST) -#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) -#elif defined(OS_WIN) - static int pixel_format_; - HDC gl_device_context_; - HGLRC gl_context_; - HPBUFFERARB pbuffer_; -#elif defined(OS_MACOSX) - CGLContextObj gl_context_; - CGLPBufferObj pbuffer_; - AcceleratedSurface surface_; -#endif - bool anti_aliased_; // The offscreen frame buffer that the client renders to. @@ -1006,6 +959,8 @@ bool Texture::AllocateStorage(const gfx::Size& size) { GL_UNSIGNED_BYTE, NULL); + size_ = size; + return glGetError() == GL_NO_ERROR; } @@ -1136,14 +1091,9 @@ GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) { return new GLES2DecoderImpl(group); } -#if defined(UNIT_TEST) -#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) -#elif defined(OS_WIN) -int GLES2DecoderImpl::pixel_format_; -#endif - GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) : GLES2Decoder(group), + context_(NULL), error_bits_(0), util_(0), // TODO(gman): Set to actual num compress texture formats. pack_alignment_(4), @@ -1153,48 +1103,26 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) black_cube_texture_id_(0), bound_framebuffer_(0), bound_renderbuffer_(0), -#if defined(UNIT_TEST) -#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) -#elif defined(OS_WIN) - gl_device_context_(NULL), - gl_context_(NULL), - pbuffer_(NULL), -#elif defined(OS_MAC) - gl_context_(NULL), - pbuffer_(NULL), -#endif anti_aliased_(false) { } -bool GLES2DecoderImpl::Initialize(GLES2Decoder* parent, +bool GLES2DecoderImpl::Initialize(GLContext* context, const gfx::Size& size, + GLES2Decoder* parent, uint32 parent_client_texture_id) { + DCHECK(!context_); + context_ = context; + // Keep only a weak pointer to the parent so we don't unmap its client - // frame buffer is after it has been destroyed. + // frame buffer after it has been destroyed. if (parent) parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr(); - pending_size_ = size; - - if (!InitPlatformSpecific()) { - Destroy(); - return false; - } - if (!MakeCurrent()) { Destroy(); return false; } - // This happens in InitializeOneOff in windows. TODO(apatrick): generalize to - // other platforms. -#if !defined(OS_WIN) - if (!InitGlew()) { - Destroy(); - return false; - } -#endif - CHECK_GL_ERROR(); if (!group_->Initialize()) { @@ -1232,7 +1160,8 @@ bool GLES2DecoderImpl::Initialize(GLES2Decoder* parent, glBindTexture(GL_TEXTURE_CUBE_MAP, 0); CHECK_GL_ERROR(); - if (size.width() > 0 && size.height() > 0) { +#if !defined(UNIT_TEST) + if (context_->IsOffscreen()) { // Create the target frame buffer. This is the one that the client renders // directly to. offscreen_target_frame_buffer_.reset(new FrameBuffer(this)); @@ -1267,6 +1196,7 @@ bool GLES2DecoderImpl::Initialize(GLES2Decoder* parent, // Allocate the render buffers at their initial size and check the status // of the frame buffers is okay. + pending_offscreen_size_ = size; if (!UpdateOffscreenFrameBufferSize()) { DLOG(ERROR) << "Could not allocate offscreen buffer storage."; Destroy(); @@ -1277,6 +1207,7 @@ bool GLES2DecoderImpl::Initialize(GLES2Decoder* parent, // 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 @@ -1289,176 +1220,6 @@ bool GLES2DecoderImpl::Initialize(GLES2Decoder* parent, return true; } -// TODO(kbr): the use of this anonymous namespace core dumps the -// linker on Mac OS X 10.6 when the symbol ordering file is used -// namespace { - -#if defined(UNIT_TEST) -#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) -#elif defined(OS_WIN) - -const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = { - sizeof(kPixelFormatDescriptor), // Size of structure. - 1, // Default version. - PFD_DRAW_TO_WINDOW | // Window drawing support. - PFD_SUPPORT_OPENGL | // OpenGL support. - PFD_DOUBLEBUFFER, // Double buffering support (not stereo). - PFD_TYPE_RGBA, // RGBA color mode (not indexed). - 24, // 24 bit color mode. - 0, 0, 0, 0, 0, 0, // Don't set RGB bits & shifts. - 8, 0, // 8 bit alpha - 0, // No accumulation buffer. - 0, 0, 0, 0, // Ignore accumulation bits. - 24, // 24 bit z-buffer size. - 8, // 8-bit stencil buffer. - 0, // No aux buffer. - PFD_MAIN_PLANE, // Main drawing plane (not overlay). - 0, // Reserved. - 0, 0, 0, // Layer masks ignored. -}; - -LRESULT CALLBACK IntermediateWindowProc(HWND window, - UINT message, - WPARAM w_param, - LPARAM l_param) { - return ::DefWindowProc(window, message, w_param, l_param); -} - -// Helper routine that does one-off initialization like determining the -// pixel format and initializing glew. -bool GLES2DecoderImpl::InitializeOneOff(bool anti_aliased) { - // We must initialize a GL context before we can determine the multi-sampling - // supported on the current hardware, so we create an intermediate window - // and context here. - HINSTANCE module_handle; - if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | - GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - reinterpret_cast<wchar_t*>(IntermediateWindowProc), - &module_handle)) { - return false; - } - - WNDCLASS intermediate_class; - intermediate_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; - intermediate_class.lpfnWndProc = IntermediateWindowProc; - intermediate_class.cbClsExtra = 0; - intermediate_class.cbWndExtra = 0; - intermediate_class.hInstance = module_handle; - intermediate_class.hIcon = LoadIcon(NULL, IDI_APPLICATION); - intermediate_class.hCursor = LoadCursor(NULL, IDC_ARROW); - intermediate_class.hbrBackground = NULL; - intermediate_class.lpszMenuName = NULL; - intermediate_class.lpszClassName = L"Intermediate GL Window"; - - ATOM class_registration = ::RegisterClass(&intermediate_class); - if (!class_registration) { - return false; - } - - HWND intermediate_window = ::CreateWindow( - reinterpret_cast<wchar_t*>(class_registration), - L"", - WS_OVERLAPPEDWINDOW, - 0, 0, - CW_USEDEFAULT, CW_USEDEFAULT, - NULL, - NULL, - NULL, - NULL); - - if (!intermediate_window) { - ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration), - module_handle); - return false; - } - - HDC intermediate_dc = ::GetDC(intermediate_window); - pixel_format_ = ::ChoosePixelFormat(intermediate_dc, - &kPixelFormatDescriptor); - if (pixel_format_ == 0) { - DLOG(ERROR) << "Unable to get the pixel format for GL context."; - ::ReleaseDC(intermediate_window, intermediate_dc); - ::DestroyWindow(intermediate_window); - ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration), - module_handle); - return false; - } - if (!::SetPixelFormat(intermediate_dc, pixel_format_, - &kPixelFormatDescriptor)) { - DLOG(ERROR) << "Unable to set the pixel format for GL context."; - ::ReleaseDC(intermediate_window, intermediate_dc); - ::DestroyWindow(intermediate_window); - ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration), - module_handle); - return false; - } - - // Create a temporary GL context to query for multisampled pixel formats. - HGLRC gl_context = ::wglCreateContext(intermediate_dc); - if (::wglMakeCurrent(intermediate_dc, gl_context)) { - // GL context was successfully created and applied to the window's DC. - // Startup GLEW, the GL extensions wrangler. - if (InitGlew()) { - DLOG(INFO) << "Initialized GLEW " << glewGetString(GLEW_VERSION); - } else { - ::wglMakeCurrent(intermediate_dc, NULL); - ::wglDeleteContext(gl_context); - ::ReleaseDC(intermediate_window, intermediate_dc); - ::DestroyWindow(intermediate_window); - ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration), - module_handle); - return false; - } - - // If the multi-sample extensions are present, query the api to determine - // the pixel format. - if (anti_aliased && WGLEW_ARB_pixel_format && WGLEW_ARB_multisample) { - int pixel_attributes[] = { - WGL_SAMPLES_ARB, 4, - WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, - WGL_SUPPORT_OPENGL_ARB, GL_TRUE, - WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, - WGL_COLOR_BITS_ARB, 24, - WGL_ALPHA_BITS_ARB, 8, - WGL_DEPTH_BITS_ARB, 24, - WGL_STENCIL_BITS_ARB, 8, - WGL_DOUBLE_BUFFER_ARB, GL_TRUE, - WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, - 0, 0}; - - float pixel_attributes_f[] = {0, 0}; - int msaa_pixel_format; - unsigned int num_formats; - - // Query for the highest sampling rate supported, starting at 4x. - static const int kSampleCount[] = {4, 2}; - static const int kNumSamples = 2; - for (int sample = 0; sample < kNumSamples; ++sample) { - pixel_attributes[1] = kSampleCount[sample]; - if (GL_TRUE == ::wglChoosePixelFormatARB(intermediate_dc, - pixel_attributes, - pixel_attributes_f, - 1, - &msaa_pixel_format, - &num_formats)) { - pixel_format_ = msaa_pixel_format; - break; - } - } - } - } - - ::wglMakeCurrent(intermediate_dc, NULL); - ::wglDeleteContext(gl_context); - ::ReleaseDC(intermediate_window, intermediate_dc); - ::DestroyWindow(intermediate_window); - ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration), - module_handle); - return true; -} - -#endif // OS_WIN - // These commands convert from c calls to local os calls. void GLGenBuffersHelper( GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) { @@ -1537,36 +1298,8 @@ void GLDeleteTexturesHelper( bool GLES2DecoderImpl::MakeCurrent() { #if defined(UNIT_TEST) return true; -#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) - return true; -#elif defined(OS_WIN) - if (::wglGetCurrentDC() == gl_device_context_ && - ::wglGetCurrentContext() == gl_context_) { - return true; - } - if (!::wglMakeCurrent(gl_device_context_, gl_context_)) { - DLOG(ERROR) << "Unable to make gl context current."; - return false; - } - return true; -#elif defined(OS_LINUX) - // TODO(apatrick): offscreen rendering not yet supported on this platform. - return context()->MakeCurrent(); -#elif defined(OS_MACOSX) - if (gl_context_) { - if (CGLGetCurrentContext() != gl_context_) { - if (CGLSetCurrentContext(gl_context_) != kCGLNoError) { - DLOG(ERROR) << "Unable to make gl context current."; - return false; - } - } - return true; - } else { - return surface_.MakeCurrent(); - } #else - NOTREACHED(); - return false; + return context_->MakeCurrent(); #endif } @@ -1614,233 +1347,99 @@ void GLES2DecoderImpl::UnregisterObjects( } } -bool GLES2DecoderImpl::InitPlatformSpecific() { -#if !defined(UNIT_TEST) && !defined(OS_LINUX) - bool offscreen = pending_size_.width() > 0 && pending_size_.height() > 0; -#endif -#if defined(UNIT_TEST) -#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) -#elif defined(OS_WIN) - // Do one-off initialization. - static bool success = InitializeOneOff(anti_aliased_); - if (!success) - return false; - - if (offscreen) { - // Create a device context compatible with the primary display. - HDC display_device_context = ::CreateDC(L"DISPLAY", NULL, NULL, NULL); - - // Create a 1 x 1 pbuffer suitable for use with the device. This is just - // a stepping stone towards creating a frame buffer object. It doesn't - // matter what size it is. - const int kNoAttributes[] = { 0 }; - pbuffer_ = ::wglCreatePbufferARB(display_device_context, - pixel_format_, - 1, 1, - kNoAttributes); - ::DeleteDC(display_device_context); - if (!pbuffer_) { - DLOG(ERROR) << "Unable to create pbuffer."; - DestroyPlatformSpecific(); - return false; - } - - gl_device_context_ = ::wglGetPbufferDCARB(pbuffer_); - if (!gl_device_context_) { - DLOG(ERROR) << "Unable to get pbuffer device context."; - DestroyPlatformSpecific(); - return false; - } - } else { - // The GL context will render to this window. - gl_device_context_ = ::GetDC(hwnd()); - - if (!::SetPixelFormat(gl_device_context_, - pixel_format_, - &kPixelFormatDescriptor)) { - DLOG(ERROR) << "Unable to set the pixel format for GL context."; - DestroyPlatformSpecific(); - return false; - } - } - - gl_context_ = ::wglCreateContext(gl_device_context_); - if (!gl_context_) { - DLOG(ERROR) << "Failed to create GL context."; - DestroyPlatformSpecific(); - return false; - } +gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() { + if (bound_framebuffer_ != 0) { + int width = 0; + int height = 0; - if (parent_) { - if (!wglShareLists(parent_->gl_context_, gl_context_)) { - DLOG(ERROR) << "Could not share GL contexts."; - DestroyPlatformSpecific(); - return false; + // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and + // stencil. + GLint fb_type = 0; + glGetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, + &fb_type); + switch (fb_type) { + case GL_RENDERBUFFER: + { + GLint renderbuffer_id = 0; + glGetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + &renderbuffer_id); + if (renderbuffer_id != 0) { + glGetRenderbufferParameterivEXT( + GL_RENDERBUFFER, + GL_RENDERBUFFER_WIDTH, + &width); + glGetRenderbufferParameterivEXT( + GL_RENDERBUFFER, + GL_RENDERBUFFER_HEIGHT, + &height); + } + break; + } + case GL_TEXTURE: + { + GLint texture_id = 0; + glGetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + &texture_id); + if (texture_id != 0) { + TextureManager::TextureInfo* texture_info = + GetTextureInfo(texture_id); + if (texture_info) { + GLint level = 0; + GLint face = 0; + glGetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, + &level); + glGetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, + &face); + texture_info->GetLevelSize( + face ? face : GL_TEXTURE_2D, level, &width, &height); + } + } + break; + } + default: + // unknown so assume width and height are zero. + break; } - } -#elif defined(OS_LINUX) - // TODO(apatrick): parent contexts not yet supported on this platform. - DCHECK(!parent_); - - DCHECK(context()); - - // Offscreen / onscreen handling done earlier on this platform (in - // GPUProcessor::Initialize). - - if (!context()->Initialize()) - return false; -#elif defined(OS_MACOSX) - // TODO(apatrick): parent contexts not yet supported on this platform. - DCHECK(!parent_); - - if (offscreen) { - // Create a 1x1 pbuffer and associated context to bootstrap things - static const CGLPixelFormatAttribute attribs[] = { - (CGLPixelFormatAttribute) kCGLPFAPBuffer, - (CGLPixelFormatAttribute) 0 - }; - CGLPixelFormatObj pixel_format; - GLint num_pixel_formats; - if (CGLChoosePixelFormat(attribs, - &pixel_format, - &num_pixel_formats) != kCGLNoError) { - DLOG(ERROR) << "Error choosing pixel format."; - DestroyPlatformSpecific(); - return false; - } - if (!pixel_format) { - return false; - } - CGLError res = CGLCreateContext(pixel_format, 0, &gl_context_); - CGLDestroyPixelFormat(pixel_format); - if (res != kCGLNoError) { - DLOG(ERROR) << "Error creating context."; - DestroyPlatformSpecific(); - return false; - } - if (CGLCreatePBuffer(1, 1, - GL_TEXTURE_2D, GL_RGBA, - 0, &pbuffer_) != kCGLNoError) { - DLOG(ERROR) << "Error creating pbuffer."; - DestroyPlatformSpecific(); - return false; - } - if (CGLSetPBuffer(gl_context_, pbuffer_, 0, 0, 0) != kCGLNoError) { - DLOG(ERROR) << "Error attaching pbuffer to context."; - DestroyPlatformSpecific(); - return false; - } - return true; + return gfx::Size(width, height); + } else if (offscreen_target_color_texture_.get()) { + return offscreen_target_color_texture_->size(); } else { - return surface_.Initialize(); - } -#endif - - return true; -} - -bool GLES2DecoderImpl::InitGlew() { -#if !defined(UNIT_TEST) && !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) - DLOG(INFO) << "Initializing GL and GLEW for GLES2Decoder."; - - GLenum glew_error = glewInit(); - if (glew_error != GLEW_OK) { - DLOG(ERROR) << "Unable to initialise GLEW : " - << glewGetErrorString(glew_error); - return false; - } - - // Check to see that we can use the OpenGL vertex attribute APIs - // TODO(petersont): Return false if this check fails, but because some - // Intel hardware does not support OpenGL 2.0, yet does support all of the - // extensions we require, we only log an error. A future CL should change - // this check to ensure that all of the extension strings we require are - // present. - if (!GLEW_VERSION_2_0) { - DLOG(ERROR) << "GL drivers do not have OpenGL 2.0 functionality."; - } - - bool extensions_found = true; - if (!GLEW_ARB_vertex_buffer_object) { - // NOTE: Linux NVidia drivers claim to support OpenGL 2.0 when using - // indirect rendering (e.g. remote X), but it is actually lying. The - // ARB_vertex_buffer_object functions silently no-op (!) when using - // indirect rendering, leading to crashes. Fortunately, in that case, the - // driver claims to not support ARB_vertex_buffer_object, so fail in that - // case. - DLOG(ERROR) << "GL drivers do not support vertex buffer objects."; - extensions_found = false; - } - if (!GLEW_EXT_framebuffer_object) { - DLOG(ERROR) << "GL drivers do not support framebuffer objects."; - extensions_found = false; - } - // Check for necessary extensions - if (!GLEW_VERSION_2_0 && !GLEW_EXT_stencil_two_side) { - DLOG(ERROR) << "Two sided stencil extension missing."; - extensions_found = false; - } - if (!GLEW_VERSION_1_4 && !GLEW_EXT_blend_func_separate) { - DLOG(ERROR) <<"Separate blend func extension missing."; - extensions_found = false; - } - if (!GLEW_VERSION_2_0 && !GLEW_EXT_blend_equation_separate) { - DLOG(ERROR) << "Separate blend function extension missing."; - extensions_found = false; - } - if (!extensions_found) - return false; -#endif - - return true; -} - -void GLES2DecoderImpl::DestroyPlatformSpecific() { #if defined(UNIT_TEST) -#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) -#elif defined(OS_WIN) - if (gl_context_) { - ::wglDeleteContext(gl_context_); - } - - if (gl_device_context_) { - if (hwnd()) - ::ReleaseDC(hwnd(), gl_device_context_); - else - ::wglReleasePbufferDCARB(pbuffer_, gl_device_context_); - - gl_device_context_ = NULL; - } - - if (pbuffer_) { - ::wglDestroyPbufferARB(pbuffer_); - pbuffer_ = NULL; - } -#elif defined(OS_MAC) - if (gl_context_) { - CGLDestroyContext(gl_context_); - gl_context_ = NULL; - } - - if (pbuffer_) { - CGLDestroyPBuffer(pbuffer_); - pbuffer_ = NULL; - } + return gfx::Size(INT_MAX, INT_MAX); +#else + return context_->GetSize(); #endif + } } bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() { - if (current_size_ != pending_size_) + if (offscreen_target_color_texture_->size() == pending_offscreen_size_) return true; // Reallocate the offscreen target buffers. - if (!offscreen_target_color_texture_->AllocateStorage(pending_size_)) { + if (!offscreen_target_color_texture_->AllocateStorage( + pending_offscreen_size_)) { return false; } if (!offscreen_target_depth_stencil_render_buffer_->AllocateStorage( - pending_size_, GL_DEPTH24_STENCIL8)) { + pending_offscreen_size_, GL_DEPTH24_STENCIL8)) { return false; } @@ -1875,20 +1474,21 @@ bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() { return false; } - // Create the saved offscreen color texture. - offscreen_saved_color_texture_->AllocateStorage(pending_size_); - - // Clear the offscreen saved color texture by copying the cleared target - // frame buffer into it. - { - ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id()); - offscreen_saved_color_texture_->Copy(pending_size_); - } - // Update the info about the offscreen saved color texture in the parent. // The reference to the parent is a weak pointer and will become null if the // parent is later destroyed. if (parent_) { + // Create the saved offscreen color texture (only accessible to parent). + offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_); + + // Clear the offscreen saved color texture by copying the cleared target + // frame buffer into it. + { + ScopedFrameBufferBinder binder(this, + offscreen_target_frame_buffer_->id()); + offscreen_saved_color_texture_->Copy(pending_offscreen_size_); + } + GLuint service_id = offscreen_saved_color_texture_->id(); TextureManager::TextureInfo* info = @@ -1898,49 +1498,17 @@ bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() { info->SetLevelInfo(GL_TEXTURE_2D, 0, // level GL_RGBA, - pending_size_.width(), pending_size_.height(), + pending_offscreen_size_.width(), + pending_offscreen_size_.height(), 1, // depth 0, // border GL_RGBA, GL_UNSIGNED_BYTE); } - current_size_ = pending_size_; return true; } -#if defined(OS_MACOSX) - -uint64 GLES2DecoderImpl::SetWindowSizeForIOSurface(int32 width, int32 height) { -#if defined(UNIT_TEST) - return 0; -#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) - return 0; -#else - return surface_.SetSurfaceSize(width, height); -#endif // !defined(UNIT_TEST) -} - -TransportDIB::Handle GLES2DecoderImpl::SetWindowSizeForTransportDIB( - int32 width, int32 height) { -#if defined(UNIT_TEST) - return TransportDIB::DefaultHandleValue(); -#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) - return TransportDIB::DefaultHandleValue(); -#else - return surface_.SetTransportDIBSize(width, height); -#endif // !defined(UNIT_TEST) -} - -void GLES2DecoderImpl::SetTransportDIBAllocAndFree( - Callback2<size_t, TransportDIB::Handle*>::Type* allocator, - Callback1<TransportDIB::Id>::Type* deallocator) { -#if !defined(UNIT_TEST) - surface_.SetTransportDIBAllocAndFree(allocator, deallocator); -#endif -} -#endif // defined(OS_MACOSX) - void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) { swap_buffers_callback_.reset(callback); } @@ -1962,38 +1530,37 @@ void GLES2DecoderImpl::Destroy() { } } - if (offscreen_target_frame_buffer_.get()) + if (offscreen_target_frame_buffer_.get()) { offscreen_target_frame_buffer_->Destroy(); + offscreen_target_frame_buffer_.reset(); + } - if (offscreen_target_color_texture_.get()) + if (offscreen_target_color_texture_.get()) { offscreen_target_color_texture_->Destroy(); + offscreen_target_color_texture_.reset(); + } - if (offscreen_target_depth_stencil_render_buffer_.get()) + if (offscreen_target_depth_stencil_render_buffer_.get()) { offscreen_target_depth_stencil_render_buffer_->Destroy(); + offscreen_target_depth_stencil_render_buffer_.reset(); + } - if (temporary_frame_buffer_.get()) + if (temporary_frame_buffer_.get()) { temporary_frame_buffer_->Destroy(); + temporary_frame_buffer_.reset(); + } - if (offscreen_saved_color_texture_.get()) + if (offscreen_saved_color_texture_.get()) { offscreen_saved_color_texture_->Destroy(); - -#if defined(UNIT_TEST) -#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) -#elif defined(OS_LINUX) - DCHECK(context()); - context()->Destroy(); -#elif defined(OS_MACOSX) - surface_.Destroy(); -#endif - - DestroyPlatformSpecific(); + offscreen_saved_color_texture_.reset(); + } } void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) { // We can't resize the render buffers immediately because there might be a // partial frame rendered into them and we don't want the tail end of that // rendered into the reallocated storage. Defer until the next SwapBuffers. - pending_size_ = size; + pending_offscreen_size_ = size; } const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const { @@ -2831,77 +2398,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels( CopyRealGLErrorsToWrapper(); // Get the size of the current fbo or backbuffer. - GLsizei max_width = 0; - GLsizei max_height = 0; - if (bound_framebuffer_ != 0) { - // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and - // stencil. - GLint fb_type = 0; - glGetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, - &fb_type); - switch (fb_type) { - case GL_RENDERBUFFER: - { - GLint renderbuffer_id = 0; - glGetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, - &renderbuffer_id); - if (renderbuffer_id != 0) { - glGetRenderbufferParameterivEXT( - GL_RENDERBUFFER, - GL_RENDERBUFFER_WIDTH, - &max_width); - glGetRenderbufferParameterivEXT( - GL_RENDERBUFFER, - GL_RENDERBUFFER_HEIGHT, - &max_height); - } - break; - } - case GL_TEXTURE: - { - GLint texture_id = 0; - glGetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, - &texture_id); - if (texture_id != 0) { - TextureManager::TextureInfo* texture_info = - GetTextureInfo(texture_id); - if (texture_info) { - GLint level = 0; - GLint face = 0; - glGetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, - &level); - glGetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, - &face); - texture_info->GetLevelSize( - face ? face : GL_TEXTURE_2D, level, &max_width, &max_height); - } - } - break; - } - default: - // unknown so assume max_width = 0. - break; - } - } else { - // TODO(gman): Get these values from the proper place. - max_width = 300; - max_height = 300; - } + gfx::Size max_size = GetBoundFrameBufferSize(); GLint max_x; GLint max_y; @@ -2910,7 +2407,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels( return error::kNoError; } - if (x < 0 || y < 0 || max_x > max_width || max_y > max_height) { + if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) { // The user requested an out of range area. Get the results 1 line // at a time. uint32 temp_size; @@ -2942,7 +2439,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels( // Copy each row into the larger dest rect. int8* dst = static_cast<int8*>(pixels); GLint read_x = std::max(0, x); - GLint read_end_x = std::max(0, std::min(max_width, max_x)); + GLint read_end_x = std::max(0, std::min(max_size.width(), max_x)); GLint read_width = read_end_x - read_x; for (GLint yy = 0; yy < height; ++yy) { GLint ry = y + yy; @@ -2951,7 +2448,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels( memset(dst, 0, unpadded_row_size); // If the row is in range, copy it. - if (ry >= 0 && ry < max_height && read_width > 0) { + if (ry >= 0 && ry < max_size.height() && read_width > 0) { glReadPixels( read_x, ry, read_width, 1, format, type, dst + dest_row_offset); } @@ -3679,19 +3176,11 @@ error::Error GLES2DecoderImpl::HandleSwapBuffers( return error::kLostContext; ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id()); - offscreen_saved_color_texture_->Copy(current_size_); + offscreen_saved_color_texture_->Copy( + offscreen_saved_color_texture_->size()); } else { -#if defined(UNIT_TEST) -#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2) -#elif defined(OS_WIN) - ::SwapBuffers(gl_device_context_); -#elif defined(OS_LINUX) - DCHECK(context()); - context()->SwapBuffers(); -#elif defined(OS_MACOSX) - // TODO(kbr): Need to property hook up and track the OpenGL state and hook - // up the notion of the currently bound FBO. - surface_.SwapBuffers(); +#if !defined(UNIT_TEST) + context_->SwapBuffers(); #endif } |