 Chromium Code Reviews
 Chromium Code Reviews Issue 12017032:
  Add calls to EnsureGPUMemoryAvailable into GLES2DecoderImpl  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 12017032:
  Add calls to EnsureGPUMemoryAvailable into GLES2DecoderImpl  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| 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 1379f29cfa93bf23af1b3c3d83032ca21cb13f8a..987709406af0f3122c248409002a7ef4227e40cb 100644 | 
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc | 
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc | 
| @@ -659,6 +659,10 @@ class GLES2DecoderImpl : public GLES2Decoder { | 
| return vertex_array_manager_.get(); | 
| } | 
| + MemoryTracker* memory_tracker() { | 
| + return group_->memory_tracker(); | 
| + } | 
| + | 
| bool IsOffscreenBufferMultisampled() const { | 
| return offscreen_target_samples_ > 1; | 
| } | 
| @@ -1826,7 +1830,7 @@ ScopedTextureUploadTimer::~ScopedTextureUploadTimer() { | 
| Texture::Texture(GLES2DecoderImpl* decoder) | 
| : decoder_(decoder), | 
| - memory_tracker_(decoder->GetContextGroup()->memory_tracker(), | 
| + memory_tracker_(decoder->memory_tracker(), | 
| MemoryTracker::kUnmanaged), | 
| bytes_allocated_(0), | 
| id_(0) { | 
| @@ -1928,7 +1932,7 @@ void Texture::Invalidate() { | 
| RenderBuffer::RenderBuffer(GLES2DecoderImpl* decoder) | 
| : decoder_(decoder), | 
| - memory_tracker_(decoder->GetContextGroup()->memory_tracker(), | 
| + memory_tracker_(decoder->memory_tracker(), | 
| MemoryTracker::kUnmanaged), | 
| bytes_allocated_(0), | 
| id_(0) { | 
| @@ -4782,20 +4786,20 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample( | 
| GetRenderbufferInfoForTarget(GL_RENDERBUFFER); | 
| if (!renderbuffer) { | 
| SetGLError(GL_INVALID_OPERATION, | 
| - "glGetRenderbufferStorageMultisample", "no renderbuffer bound"); | 
| + "glRenderbufferStorageMultisampleEXT", "no renderbuffer bound"); | 
| return; | 
| } | 
| if (samples > renderbuffer_manager()->max_samples()) { | 
| SetGLError(GL_INVALID_VALUE, | 
| - "glGetRenderbufferStorageMultisample", "samples too large"); | 
| + "glRenderbufferStorageMultisampleEXT", "samples too large"); | 
| return; | 
| } | 
| if (width > renderbuffer_manager()->max_renderbuffer_size() || | 
| height > renderbuffer_manager()->max_renderbuffer_size()) { | 
| SetGLError(GL_INVALID_VALUE, | 
| - "glGetRenderbufferStorageMultisample", "size too large"); | 
| + "glRenderbufferStorageMultisample", "dimensions too large"); | 
| return; | 
| } | 
| @@ -4815,6 +4819,20 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample( | 
| } | 
| } | 
| + uint32 estimated_size = 0; | 
| + if (!GLES2Util::ComputeEstimatedRenderbufferSize( | 
| + width, height, samples, impl_format, &estimated_size)) { | 
| + SetGLError(GL_OUT_OF_MEMORY, | 
| + "glRenderbufferStorageMultsampleEXT", "dimensions too large"); | 
| + return; | 
| + } | 
| + | 
| + if (!memory_tracker()->EnsureGPUMemoryAvailable(estimated_size)) { | 
| + SetGLError(GL_OUT_OF_MEMORY, | 
| + "glRenderbufferStorageMultsampleEXT", "out of memory"); | 
| + return; | 
| + } | 
| + | 
| CopyRealGLErrorsToWrapper(); | 
| if (IsAngle()) { | 
| glRenderbufferStorageMultisampleANGLE( | 
| @@ -4839,14 +4857,14 @@ void GLES2DecoderImpl::DoRenderbufferStorage( | 
| GetRenderbufferInfoForTarget(GL_RENDERBUFFER); | 
| if (!renderbuffer) { | 
| SetGLError(GL_INVALID_OPERATION, | 
| - "glGetRenderbufferStorage", "no renderbuffer bound"); | 
| + "glRenderbufferStorage", "no renderbuffer bound"); | 
| return; | 
| } | 
| if (width > renderbuffer_manager()->max_renderbuffer_size() || | 
| height > renderbuffer_manager()->max_renderbuffer_size()) { | 
| SetGLError(GL_INVALID_VALUE, | 
| - "glGetRenderbufferStorage", "size too large"); | 
| + "glRenderbufferStorage", "dimensions too large"); | 
| return; | 
| } | 
| @@ -4866,6 +4884,19 @@ void GLES2DecoderImpl::DoRenderbufferStorage( | 
| } | 
| } | 
| + uint32 estimated_size = 0; | 
| + if (!GLES2Util::ComputeEstimatedRenderbufferSize( | 
| + width, height, 1, impl_format, &estimated_size)) { | 
| + SetGLError(GL_OUT_OF_MEMORY, "glRenderbufferStorage", | 
| + "dimensions too large"); | 
| + return; | 
| + } | 
| + | 
| + if (!memory_tracker()->EnsureGPUMemoryAvailable(estimated_size)) { | 
| + SetGLError(GL_OUT_OF_MEMORY, "glRenderbufferStorage", "out of memory"); | 
| + return; | 
| + } | 
| + | 
| CopyRealGLErrorsToWrapper(); | 
| glRenderbufferStorageEXT(target, impl_format, width, height); | 
| GLenum error = PeekGLError(); | 
| @@ -7091,6 +7122,12 @@ void GLES2DecoderImpl::DoBufferData( | 
| SetGLError(GL_INVALID_VALUE, "glBufferData", "unknown buffer"); | 
| return; | 
| } | 
| + | 
| + if (!memory_tracker()->EnsureGPUMemoryAvailable(size)) { | 
| + SetGLError(GL_OUT_OF_MEMORY, "glBufferData", "out of memory"); | 
| + return; | 
| + } | 
| + | 
| // Clear the buffer to 0 if no initial data was passed in. | 
| scoped_array<int8> zero; | 
| if (!data) { | 
| @@ -7442,6 +7479,11 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D( | 
| return error::kNoError; | 
| } | 
| + if (!memory_tracker()->EnsureGPUMemoryAvailable(image_size)) { | 
| + SetGLError(GL_OUT_OF_MEMORY, "glCompressedTexImage2D", "out of memory"); | 
| + return error::kNoError; | 
| + } | 
| + | 
| if (info->IsAttachedToFramebuffer()) { | 
| clear_state_dirty_ = true; | 
| // TODO(gman): If textures tracked which framebuffers they were attached to | 
| @@ -7676,6 +7718,12 @@ void GLES2DecoderImpl::DoTexImage2D( | 
| width, height, border, format, type, pixels, pixels_size)) { | 
| return; | 
| } | 
| + | 
| + if (!memory_tracker()->EnsureGPUMemoryAvailable(pixels_size)) { | 
| + SetGLError(GL_OUT_OF_MEMORY, "glTexImage2D", "out of memory"); | 
| + return; | 
| + } | 
| + | 
| TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); | 
| GLsizei tex_width = 0; | 
| GLsizei tex_height = 0; | 
| @@ -7902,7 +7950,20 @@ void GLES2DecoderImpl::DoCopyTexImage2D( | 
| if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) { | 
| SetGLError( | 
| GL_INVALID_OPERATION, | 
| - "glCopyImage2D", "can not be used with depth or stencil textures"); | 
| + "glCopyTexImage2D", "can not be used with depth or stencil textures"); | 
| + return; | 
| + } | 
| + | 
| + uint32 estimated_size = 0; | 
| + if (!GLES2Util::ComputeImageDataSizes( | 
| + width, height, internal_format, GL_UNSIGNED_BYTE, state_.unpack_alignment, | 
| + &estimated_size, NULL, NULL)) { | 
| + SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large"); | 
| + return; | 
| + } | 
| + | 
| + if (!memory_tracker()->EnsureGPUMemoryAvailable(estimated_size)) { | 
| 
ccameron
2013/01/19 01:38:46
So that we can take into account the current usage
 | 
| + SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory"); | 
| return; | 
| } | 
| @@ -9575,13 +9636,38 @@ void GLES2DecoderImpl::DoTexStorage2DEXT( | 
| "glTexStorage2DEXT", "texture is immutable"); | 
| return; | 
| } | 
| + | 
| + GLenum format = ExtractFormatFromStorageFormat(internal_format); | 
| + GLenum type = ExtractTypeFromStorageFormat(internal_format); | 
| + | 
| + { | 
| + GLsizei level_width = width; | 
| + GLsizei level_height = height; | 
| + uint32 estimated_size = 0; | 
| + for (int ii = 0; ii < levels; ++ii) { | 
| + uint32 level_size = 0; | 
| + if (!GLES2Util::ComputeImageDataSizes( | 
| + level_width, level_height, format, type, state_.unpack_alignment, | 
| + &estimated_size, NULL, NULL) || | 
| + !SafeAddUint32(estimated_size, level_size, &estimated_size)) { | 
| + SetGLError(GL_OUT_OF_MEMORY, | 
| + "glTexStorage2DEXT", "dimensions too large"); | 
| + return; | 
| + } | 
| + level_width = std::max(1, level_width >> 1); | 
| + level_height = std::max(1, level_height >> 1); | 
| + } | 
| + if (!memory_tracker()->EnsureGPUMemoryAvailable(estimated_size)) { | 
| + SetGLError(GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory"); | 
| + return; | 
| + } | 
| + } | 
| + | 
| CopyRealGLErrorsToWrapper(); | 
| glTexStorage2DEXT(target, levels, GetTexInternalFormat(internal_format), | 
| width, height); | 
| GLenum error = PeekGLError(); | 
| if (error == GL_NO_ERROR) { | 
| - GLenum format = ExtractFormatFromStorageFormat(internal_format); | 
| - GLenum type = ExtractTypeFromStorageFormat(internal_format); | 
| GLsizei level_width = width; | 
| GLsizei level_height = height; | 
| for (int ii = 0; ii < levels; ++ii) { | 
| @@ -9883,6 +9969,11 @@ error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM( | 
| return error::kNoError; | 
| } | 
| + if (!memory_tracker()->EnsureGPUMemoryAvailable(pixels_size)) { | 
| + SetGLError(GL_OUT_OF_MEMORY, "glAsyncTexImage2DCHROMIUM", "out of memory"); | 
| + return error::kNoError; | 
| + } | 
| + | 
| // We know the memory/size is safe, so get the real shared memory since | 
| // it might need to be duped to prevent use-after-free of the memory. | 
| Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id); |