Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Unified Diff: gpu/command_buffer/service/gles2_cmd_decoder.cc

Issue 8341128: Defer clearing textures and renderbuffers (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix one more unit test Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gpu/command_buffer/service/gles2_cmd_decoder.h ('k') | gpu/command_buffer/service/gles2_cmd_decoder_mock.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 c525908a1f14913df300d49dfcacb0073f1bd710..2c22ae0dfb98ec1ee6700452d3d116141a7b7e3e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -353,9 +353,6 @@ class FrameBuffer {
// currently bound frame buffer.
void AttachRenderBuffer(GLenum target, RenderBuffer* render_buffer);
- // Clear the given attached buffers.
- void Clear(GLbitfield buffers);
-
// Destroy the frame buffer. This must be explicitly called before destroying
// this object.
void Destroy();
@@ -512,6 +509,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
virtual gfx::GLSurface* GetGLSurface() { return surface_.get(); }
virtual ContextGroup* GetContextGroup() { return group_.get(); }
+ virtual void SetGLError(GLenum error, const char* msg);
virtual void SetResizeCallback(Callback1<gfx::Size>::Type* callback);
#if defined(OS_MACOSX)
@@ -844,10 +842,29 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
error::Error ShaderSourceHelper(
GLuint client_id, const char* data, uint32 data_size);
- // Clears any uncleared render buffers attached to the given frame buffer.
- void ClearUnclearedRenderbuffers(
+ // Clear any textures used by the current program.
+ bool ClearUnclearedTextures();
+
+ // Clear any uncleared level in texture.
+ // Returns false if there was a generated GL error.
+ bool ClearTexture(TextureManager::TextureInfo* info);
+
+ // Clears any uncleared attachments attached to the given frame buffer.
+ // Returns false if there was a generated GL error.
+ void ClearUnclearedAttachments(
GLenum target, FramebufferManager::FramebufferInfo* info);
+ // overridden from GLES2Decoder
+ virtual bool ClearLevel(
+ unsigned service_id,
+ unsigned bind_target,
+ unsigned target,
+ int level,
+ unsigned format,
+ unsigned type,
+ int width,
+ int height);
+
// Restore all GL state that affects clearing.
void RestoreClearState();
@@ -855,8 +872,15 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// Returns: true if glEnable/glDisable should actually be called.
bool SetCapabilityState(GLenum cap, bool enabled);
- // Check that the current frame buffer is complete. Generates error if not.
- bool CheckFramebufferComplete(const char* func_name);
+ // Check that the currently bound framebuffers are valid.
+ // Generates GL error if not.
+ bool CheckBoundFramebuffersValid(const char* func_name);
+
+ // Check if a framebuffer meets our requirements.
+ bool CheckFramebufferValid(
+ FramebufferManager::FramebufferInfo* framebuffer,
+ GLenum target,
+ const char* func_name);
// Checks if the current program exists and is valid. If not generates the
// appropriate GL error. Returns true if the current program is in a usable
@@ -1088,9 +1112,6 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// this lets us peek at the error without losing it.
GLenum PeekGLError();
- // Sets our wrapper for the GLError.
- void SetGLError(GLenum error, const char* msg);
-
// Copies the real GL errors to the wrapper. This is so we can
// make sure there are no native GL errors before calling some GL function
// so that on return we know any error generated was for that specific
@@ -1183,6 +1204,20 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
return (info && !info->IsDeleted()) ? info : NULL;
}
+ RenderbufferManager::RenderbufferInfo* GetRenderbufferInfoForTarget(
+ GLenum target) {
+ RenderbufferManager::RenderbufferInfo* info = NULL;
+ switch (target) {
+ case GL_RENDERBUFFER:
+ info = bound_renderbuffer_;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ return (info && !info->IsDeleted()) ? info : NULL;
+ }
+
// Validates the program and location for a glGetUniform call and returns
// a SizeResult setup to receive the result. Returns true if glGetUniform
// should be called.
@@ -1666,12 +1701,6 @@ void FrameBuffer::AttachRenderBuffer(GLenum target,
attach_id);
}
-void FrameBuffer::Clear(GLbitfield buffers) {
- ScopedGLErrorSuppressor suppressor(decoder_);
- ScopedFrameBufferBinder binder(decoder_, id_);
- glClear(buffers);
-}
-
void FrameBuffer::Destroy() {
if (id_ != 0) {
ScopedGLErrorSuppressor suppressor(decoder_);
@@ -2224,9 +2253,10 @@ bool GLES2DecoderImpl::MakeCurrent() {
}
void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
+ RenderbufferManager::RenderbufferInfo* renderbuffer =
+ GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
glBindRenderbufferEXT(
- GL_RENDERBUFFER,
- bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0);
+ GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
}
static void RebindCurrentFramebuffer(
@@ -2275,19 +2305,59 @@ void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
}
-bool GLES2DecoderImpl::CheckFramebufferComplete(const char* func_name) {
- if (bound_draw_framebuffer_ && bound_draw_framebuffer_->IsNotComplete()) {
- SetGLError(GL_INVALID_FRAMEBUFFER_OPERATION,
- (std::string(func_name) + " framebuffer incomplete").c_str());
+bool GLES2DecoderImpl::CheckFramebufferValid(
+ FramebufferManager::FramebufferInfo* framebuffer,
+ GLenum target, const char* func_name) {
+ if (!framebuffer || framebuffer->IsDeleted()) {
+ return true;
+ }
+
+ GLenum completeness = framebuffer->IsPossiblyComplete();
+ if (completeness != GL_FRAMEBUFFER_COMPLETE) {
+ SetGLError(
+ GL_INVALID_FRAMEBUFFER_OPERATION,
+ (std::string(func_name) + " framebuffer incomplete").c_str());
return false;
}
+
+ // Are all the attachments cleared?
+ if (renderbuffer_manager()->HaveUnclearedRenderbuffers() ||
+ texture_manager()->HaveUnclearedMips()) {
+ if (!framebuffer->IsCleared()) {
+ // Can we clear them?
+ if (glCheckFramebufferStatusEXT(target) != GL_FRAMEBUFFER_COMPLETE) {
+ SetGLError(
+ GL_INVALID_FRAMEBUFFER_OPERATION,
+ (std::string(func_name) +
+ " framebuffer incomplete (clear)").c_str());
+ return false;
+ }
+ ClearUnclearedAttachments(target, framebuffer);
+ }
+ }
+
+ // NOTE: At this point we don't know if the framebuffer is complete but
+ // we DO know that everything that needs to be cleared has been cleared.
return true;
}
+bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
+ if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
+ return CheckFramebufferValid(
+ bound_draw_framebuffer_, GL_FRAMEBUFFER_EXT, func_name);
+ }
+ return CheckFramebufferValid(
+ bound_draw_framebuffer_, GL_DRAW_FRAMEBUFFER_EXT, func_name) &&
+ CheckFramebufferValid(
+ bound_read_framebuffer_, GL_READ_FRAMEBUFFER_EXT, func_name);
+}
+
gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
- if (bound_read_framebuffer_ != 0) {
+ FramebufferManager::FramebufferInfo* framebuffer =
+ GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
+ if (framebuffer != NULL) {
const FramebufferManager::FramebufferInfo::Attachment* attachment =
- bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
+ framebuffer->GetAttachment(GL_COLOR_ATTACHMENT0);
if (attachment) {
return gfx::Size(attachment->width(), attachment->height());
}
@@ -2300,8 +2370,10 @@ gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
}
GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
- if (bound_read_framebuffer_ != 0) {
- return bound_read_framebuffer_->GetColorAttachmentFormat();
+ FramebufferManager::FramebufferInfo* framebuffer =
+ GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
+ if (framebuffer != NULL) {
+ return framebuffer->GetColorAttachmentFormat();
} else if (offscreen_target_frame_buffer_.get()) {
return offscreen_target_color_format_;
} else {
@@ -2310,8 +2382,10 @@ GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
}
GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
- if (bound_draw_framebuffer_ != 0) {
- return bound_draw_framebuffer_->GetColorAttachmentFormat();
+ FramebufferManager::FramebufferInfo* framebuffer =
+ GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
+ if (framebuffer != NULL) {
+ return framebuffer->GetColorAttachmentFormat();
} else if (offscreen_target_frame_buffer_.get()) {
return offscreen_target_color_format_;
} else {
@@ -2342,7 +2416,8 @@ void GLES2DecoderImpl::UpdateParentTextureInfo() {
1, // depth
0, // border
GL_RGBA,
- GL_UNSIGNED_BYTE);
+ GL_UNSIGNED_BYTE,
+ true);
parent_texture_manager->SetParameter(
feature_info_,
info,
@@ -2803,8 +2878,10 @@ bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
}
bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
- if (bound_draw_framebuffer_) {
- return bound_draw_framebuffer_->HasDepthAttachment();
+ FramebufferManager::FramebufferInfo* framebuffer =
+ GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
+ if (framebuffer) {
+ return framebuffer->HasDepthAttachment();
}
if (offscreen_target_frame_buffer_.get()) {
return offscreen_target_depth_format_ != 0;
@@ -2813,8 +2890,10 @@ bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
}
bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
- if (bound_draw_framebuffer_) {
- return bound_draw_framebuffer_->HasStencilAttachment();
+ FramebufferManager::FramebufferInfo* framebuffer =
+ GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
+ if (framebuffer) {
+ return framebuffer->HasStencilAttachment();
}
if (offscreen_target_frame_buffer_.get()) {
return offscreen_target_stencil_format_ != 0 ||
@@ -3217,10 +3296,12 @@ bool GLES2DecoderImpl::GetHelper(
// case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
*num_written = 1;
if (params) {
- if (bound_draw_framebuffer_) {
+ FramebufferManager::FramebufferInfo* framebuffer =
+ GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER);
+ if (framebuffer) {
GLuint client_id = 0;
framebuffer_manager()->GetClientId(
- bound_draw_framebuffer_->service_id(), &client_id);
+ framebuffer->service_id(), &client_id);
*params = client_id;
} else {
*params = 0;
@@ -3230,10 +3311,12 @@ bool GLES2DecoderImpl::GetHelper(
case GL_READ_FRAMEBUFFER_BINDING:
*num_written = 1;
if (params) {
- if (bound_read_framebuffer_) {
+ FramebufferManager::FramebufferInfo* framebuffer =
+ GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
+ if (framebuffer) {
GLuint client_id = 0;
framebuffer_manager()->GetClientId(
- bound_read_framebuffer_->service_id(), &client_id);
+ framebuffer->service_id(), &client_id);
*params = client_id;
} else {
*params = 0;
@@ -3243,10 +3326,12 @@ bool GLES2DecoderImpl::GetHelper(
case GL_RENDERBUFFER_BINDING:
*num_written = 1;
if (params) {
- if (bound_renderbuffer_) {
+ RenderbufferManager::RenderbufferInfo* renderbuffer =
+ GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
+ if (renderbuffer) {
GLuint client_id = 0;
renderbuffer_manager()->GetClientId(
- bound_renderbuffer_->service_id(), &client_id);
+ renderbuffer->service_id(), &client_id);
*params = client_id;
} else {
*params = 0;
@@ -3564,7 +3649,7 @@ error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
}
void GLES2DecoderImpl::DoClear(GLbitfield mask) {
- if (CheckFramebufferComplete("glClear")) {
+ if (CheckBoundFramebuffersValid("glClear")) {
ApplyDirtyState();
glClear(mask);
}
@@ -3597,12 +3682,6 @@ void GLES2DecoderImpl::DoFramebufferRenderbuffer(
GLenum error = PeekGLError();
if (error == GL_NO_ERROR) {
framebuffer_info->AttachRenderbuffer(attachment, info);
- if (service_id == 0 ||
- glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
- if (info) {
- ClearUnclearedRenderbuffers(target, framebuffer_info);
- }
- }
}
if (framebuffer_info == bound_draw_framebuffer_) {
state_dirty_ = true;
@@ -3693,20 +3772,24 @@ void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
state_dirty_ = true;
}
-// NOTE: There's an assumption here that Texture attachments
-// are cleared because they are textures so we only need to clear
-// the renderbuffers.
-void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
+// Assumes framebuffer is complete.
+void GLES2DecoderImpl::ClearUnclearedAttachments(
GLenum target, FramebufferManager::FramebufferInfo* info) {
+ DCHECK(!info->IsDeleted());
if (target == GL_READ_FRAMEBUFFER_EXT) {
- // TODO(gman): bind this to the DRAW point, clear then bind back to READ
+ // bind this to the DRAW point, clear then bind back to READ
+ // TODO(gman): I don't think there is any guarantee that an FBO that
+ // is complete on the READ attachment will be complete as a DRAW
+ // attachment.
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
+ glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, info->service_id());
}
GLbitfield clear_bits = 0;
if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
glClearColor(
- 0, 0, 0,
+ 0.0f, 0.0f, 0.0f,
(GLES2Util::GetChannelsForFormat(
- info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0 : 1);
+ info->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : 1.0f);
glColorMask(true, true, true, true);
clear_bits |= GL_COLOR_BUFFER_BIT;
}
@@ -3728,12 +3811,16 @@ void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
glDisable(GL_SCISSOR_TEST);
glClear(clear_bits);
- info->MarkAttachedRenderbuffersAsCleared();
+ info->MarkAttachmentsAsCleared(renderbuffer_manager(), texture_manager());
RestoreClearState();
if (target == GL_READ_FRAMEBUFFER_EXT) {
- // TODO(gman): rebind draw.
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, info->service_id());
+ FramebufferManager::FramebufferInfo*framebuffer =
+ GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER);
+ glBindFramebufferEXT(
+ GL_DRAW_FRAMEBUFFER_EXT, framebuffer ? framebuffer->service_id() : 0);
}
}
@@ -3748,11 +3835,15 @@ void GLES2DecoderImpl::RestoreClearState() {
}
GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
- FramebufferManager::FramebufferInfo* info =
+ FramebufferManager::FramebufferInfo* framebuffer =
GetFramebufferInfoForTarget(target);
- if (!info) {
+ if (!framebuffer) {
return GL_FRAMEBUFFER_COMPLETE;
}
+ GLenum completeness = framebuffer->IsPossiblyComplete();
+ if (completeness != GL_FRAMEBUFFER_COMPLETE) {
+ return completeness;
+ }
return glCheckFramebufferStatusEXT(target);
}
@@ -3777,15 +3868,19 @@ void GLES2DecoderImpl::DoFramebufferTexture2D(
}
service_id = info->service_id();
}
+
+ if (!texture_manager()->ValidForTarget(
+ feature_info_, textarget, level, 0, 0, 1)) {
+ SetGLError(GL_INVALID_VALUE,
+ "glFramebufferTexture2D: level out of range");
+ return;
+ }
+
CopyRealGLErrorsToWrapper();
glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
GLenum error = PeekGLError();
if (error == GL_NO_ERROR) {
framebuffer_info->AttachTexture(attachment, info, textarget, level);
- if (service_id != 0 &&
- glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
- ClearUnclearedRenderbuffers(target, framebuffer_info);
- }
}
if (framebuffer_info == bound_draw_framebuffer_) {
state_dirty_ = true;
@@ -3825,20 +3920,22 @@ void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
GLenum target, GLenum pname, GLint* params) {
- if (!bound_renderbuffer_) {
+ RenderbufferManager::RenderbufferInfo* renderbuffer =
+ GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
+ if (!renderbuffer) {
SetGLError(GL_INVALID_OPERATION,
"glGetRenderbufferParameteriv: no renderbuffer bound");
return;
}
switch (pname) {
case GL_RENDERBUFFER_INTERNAL_FORMAT:
- *params = bound_renderbuffer_->internal_format();
+ *params = renderbuffer->internal_format();
break;
case GL_RENDERBUFFER_WIDTH:
- *params = bound_renderbuffer_->width();
+ *params = renderbuffer->width();
break;
case GL_RENDERBUFFER_HEIGHT:
- *params = bound_renderbuffer_->height();
+ *params = renderbuffer->height();
break;
default:
glGetRenderbufferParameterivEXT(target, pname, params);
@@ -3872,6 +3969,14 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
return;
}
+ RenderbufferManager::RenderbufferInfo* renderbuffer =
+ GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
+ if (!renderbuffer) {
+ SetGLError(GL_INVALID_OPERATION,
+ "glGetRenderbufferStorageMultisample: no renderbuffer bound");
+ return;
+ }
+
if (samples > renderbuffer_manager()->max_samples()) {
SetGLError(GL_INVALID_VALUE,
"glGetRenderbufferStorageMultisample: samples too large");
@@ -3911,13 +4016,16 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
}
GLenum error = PeekGLError();
if (error == GL_NO_ERROR) {
- bound_renderbuffer_->SetInfo(samples, internalformat, width, height);
+ renderbuffer_manager()->SetInfo(
+ renderbuffer, samples, internalformat, width, height);
}
}
void GLES2DecoderImpl::DoRenderbufferStorage(
GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
- if (!bound_renderbuffer_) {
+ RenderbufferManager::RenderbufferInfo* renderbuffer =
+ GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
+ if (!renderbuffer) {
SetGLError(GL_INVALID_OPERATION,
"glGetRenderbufferStorage: no renderbuffer bound");
return;
@@ -3950,7 +4058,8 @@ void GLES2DecoderImpl::DoRenderbufferStorage(
glRenderbufferStorageEXT(target, impl_format, width, height);
GLenum error = PeekGLError();
if (error == GL_NO_ERROR) {
- bound_renderbuffer_->SetInfo(0, internalformat, width, height);
+ renderbuffer_manager()->SetInfo(
+ renderbuffer, 0, internalformat, width, height);
}
}
@@ -4370,6 +4479,38 @@ void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
}
+bool GLES2DecoderImpl::ClearUnclearedTextures() {
+ // Only check if there are some uncleared textures.
+ if (!texture_manager()->HaveUnsafeTextures()) {
+ return true;
+ }
+
+ // 1: Check all textures we are about to render with.
+ if (current_program_) {
+ const ProgramManager::ProgramInfo::SamplerIndices& sampler_indices =
+ current_program_->sampler_indices();
+ for (size_t ii = 0; ii < sampler_indices.size(); ++ii) {
+ const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
+ current_program_->GetUniformInfo(sampler_indices[ii]);
+ DCHECK(uniform_info);
+ for (size_t jj = 0; jj < uniform_info->texture_units.size(); ++jj) {
+ GLuint texture_unit_index = uniform_info->texture_units[jj];
+ if (texture_unit_index < group_->max_texture_units()) {
+ TextureUnit& texture_unit = texture_units_[texture_unit_index];
+ TextureManager::TextureInfo* texture_info =
+ texture_unit.GetInfoForSamplerType(uniform_info->type);
+ if (texture_info && !texture_info->SafeToRenderFrom()) {
+ if (!texture_manager()->ClearRenderableLevels(this, texture_info)) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
// NOTE: We specifically do not check current_program->IsValid() because
// it could never be invalid since glUseProgram would have failed. While
@@ -4604,7 +4745,7 @@ error::Error GLES2DecoderImpl::HandleDrawArrays(
SetGLError(GL_INVALID_VALUE, "glDrawArrays: count < 0");
return error::kNoError;
}
- if (!CheckFramebufferComplete("glDrawArrays")) {
+ if (!CheckBoundFramebuffersValid("glDrawArrays")) {
return error::kNoError;
}
// We have to check this here because the prototype for glDrawArrays
@@ -4620,6 +4761,10 @@ error::Error GLES2DecoderImpl::HandleDrawArrays(
GLuint max_vertex_accessed = first + count - 1;
if (IsDrawValid(max_vertex_accessed)) {
+ if (!ClearUnclearedTextures()) {
+ SetGLError(GL_INVALID_VALUE, "glDrawArrays: out of memory");
+ return error::kNoError;
+ }
bool simulated_attrib_0 = false;
if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
return error::kNoError;
@@ -4677,7 +4822,7 @@ error::Error GLES2DecoderImpl::HandleDrawElements(
return error::kNoError;
}
- if (!CheckFramebufferComplete("glDrawElements")) {
+ if (!CheckBoundFramebuffersValid("glDrawElements")) {
return error::kNoError;
}
@@ -4694,6 +4839,10 @@ error::Error GLES2DecoderImpl::HandleDrawElements(
}
if (IsDrawValid(max_vertex_accessed)) {
+ if (!ClearUnclearedTextures()) {
+ SetGLError(GL_INVALID_VALUE, "glDrawElements: out of memory");
+ return error::kNoError;
+ }
bool simulated_attrib_0 = false;
if (!SimulateAttrib0(max_vertex_accessed, &simulated_attrib_0)) {
return error::kNoError;
@@ -5376,6 +5525,10 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
return error::kNoError;
}
+ if (!CheckBoundFramebuffersValid("glReadPixels")) {
+ return error::kNoError;
+ }
+
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.
@@ -5791,6 +5944,31 @@ void GLES2DecoderImpl::DoBufferSubData(
glBufferSubData(target, offset, size, data);
}
+bool GLES2DecoderImpl::ClearLevel(
+ unsigned service_id,
+ unsigned bind_target,
+ unsigned target,
+ int level,
+ unsigned format,
+ unsigned type,
+ int width,
+ int height) {
+ // Assumes the size has already been checked.
+ uint32 pixels_size = 0;
+ if (!GLES2Util::ComputeImageDataSize(
+ width, height, format, type, unpack_alignment_, &pixels_size)) {
+ return false;
+ }
+ scoped_array<char> zero(new char[pixels_size]);
+ memset(zero.get(), 0, pixels_size);
+ glBindTexture(bind_target, service_id);
+ WrappedTexImage2D(
+ target, level, format, width, height, 0, format, type, zero.get());
+ TextureManager::TextureInfo* info = GetTextureInfoForTarget(bind_target);
+ glBindTexture(bind_target, info ? info->service_id() : 0);
+ return true;
+}
+
error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
GLenum target,
GLint level,
@@ -5838,7 +6016,8 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
if (error == GL_NO_ERROR) {
texture_manager()->SetLevelInfo(
feature_info_,
- info, target, level, internal_format, width, height, 1, border, 0, 0);
+ info, target, level, internal_format, width, height, 1, border, 0, 0,
+ true);
}
return error::kNoError;
}
@@ -6014,13 +6193,6 @@ error::Error GLES2DecoderImpl::DoTexImage2D(
return error::kNoError;
}
- scoped_array<int8> zero;
- if (!pixels) {
- zero.reset(new int8[pixels_size]);
- memset(zero.get(), 0, pixels_size);
- pixels = zero.get();
- }
-
if (info->IsAttachedToFramebuffer()) {
state_dirty_ = true;
}
@@ -6037,8 +6209,10 @@ error::Error GLES2DecoderImpl::DoTexImage2D(
pixels);
GLenum error = PeekGLError();
if (error == GL_NO_ERROR) {
- texture_manager()->SetLevelInfo(feature_info_, info,
- target, level, internal_format, width, height, 1, border, format, type);
+ texture_manager()->SetLevelInfo(
+ feature_info_, info,
+ target, level, internal_format, width, height, 1, border, format, type,
+ pixels != NULL);
tex_image_2d_failed_ = false;
}
return error::kNoError;
@@ -6138,6 +6312,10 @@ void GLES2DecoderImpl::DoCompressedTexSubImage2D(
"glCompressdTexSubImage2D: bad dimensions.");
return;
}
+ // Note: There is no need to deal with texture cleared tracking here
+ // because the validation above means you can only get here if the level
+ // is already a matching compressed format and in that case
+ // CompressedTexImage2D already cleared the texture.
glCompressedTexSubImage2D(
target, level, xoffset, yoffset, width, height, format, image_size, data);
}
@@ -6159,7 +6337,6 @@ static void Clip(
*out_range = range;
}
-
void GLES2DecoderImpl::DoCopyTexImage2D(
GLenum target,
GLint level,
@@ -6213,17 +6390,12 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
copyWidth != width ||
copyHeight != height) {
// some part was clipped so clear the texture.
- uint32 pixels_size = 0;
- if (!GLES2Util::ComputeImageDataSize(
- width, height, internal_format, GL_UNSIGNED_BYTE,
- unpack_alignment_, &pixels_size)) {
- SetGLError(GL_INVALID_VALUE, "glCopyTexImage2D: dimensions too large");
+ if (!ClearLevel(
+ info->service_id(), info->target(),
+ target, level, internal_format, GL_UNSIGNED_BYTE, width, height)) {
+ SetGLError(GL_OUT_OF_MEMORY, "glCopyTexImage2D: dimensions too big");
return;
}
- scoped_array<char> zero(new char[pixels_size]);
- memset(zero.get(), 0, pixels_size);
- glTexImage2D(target, level, internal_format, width, height, 0,
- internal_format, GL_UNSIGNED_BYTE, zero.get());
if (copyHeight > 0 && copyWidth > 0) {
GLint dx = copyX - x;
GLint dy = copyY - y;
@@ -6241,7 +6413,7 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
if (error == GL_NO_ERROR) {
texture_manager()->SetLevelInfo(
feature_info_, info, target, level, internal_format, width, height, 1,
- border, internal_format, GL_UNSIGNED_BYTE);
+ border, internal_format, GL_UNSIGNED_BYTE, true);
}
}
@@ -6289,11 +6461,17 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D(
GLint copyHeight = 0;
Clip(x, width, size.width(), &copyX, &copyWidth);
Clip(y, height, size.height(), &copyY, &copyHeight);
+
+ if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
+ SetGLError(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D: dimensions too big");
+ return;
+ }
+
if (copyX != x ||
copyY != y ||
copyWidth != width ||
copyHeight != height) {
- // some part was clipped so clear the texture.
+ // some part was clipped so clear the sub rect.
uint32 pixels_size = 0;
if (!GLES2Util::ComputeImageDataSize(
width, height, format, type, unpack_alignment_, &pixels_size)) {
@@ -6306,6 +6484,7 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D(
target, level, xoffset, yoffset, width, height,
format, type, zero.get());
}
+
if (copyHeight > 0 && copyWidth > 0) {
GLint dx = copyX - x;
GLint dy = copyY - y;
@@ -6370,9 +6549,14 @@ void GLES2DecoderImpl::DoTexSubImage2D(
// same as internal_foramt. If that changes we'll need to look them up.
WrappedTexImage2D(
target, level, format, width, height, 0, format, type, data);
+ texture_manager()->SetLevelCleared(info, target, level);
return;
}
}
+ if (!texture_manager()->ClearTextureLevel(this, info, target, level)) {
+ SetGLError(GL_OUT_OF_MEMORY, "glTexSubImage2D: dimensions too big");
+ return;
+ }
glTexSubImage2D(
target, level, xoffset, yoffset, width, height, format, type, data);
}
« no previous file with comments | « gpu/command_buffer/service/gles2_cmd_decoder.h ('k') | gpu/command_buffer/service/gles2_cmd_decoder_mock.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698