summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorkloveless@chromium.org <kloveless@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-14 01:04:44 +0000
committerkloveless@chromium.org <kloveless@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-14 01:04:44 +0000
commitc986af50bebe985a8b610ad20151f571f9548d70 (patch)
treeffd60c8f14b0c8ec31de2d12d5d3b2f21ab25b58 /gpu
parent4fe5b9dc4018358bd042276cb2bce7391698c36c (diff)
downloadchromium_src-c986af50bebe985a8b610ad20151f571f9548d70.zip
chromium_src-c986af50bebe985a8b610ad20151f571f9548d70.tar.gz
chromium_src-c986af50bebe985a8b610ad20151f571f9548d70.tar.bz2
Moved DoTexImage2D and its validation into the TextureManager.
Added DecoderTextureState and DecoderFramebufferState to hold information used by those managers, but were decoder specific. To simplify passing arguments around, [ValidateAnd]DoTextImage2d take a structure. Review URL: https://chromiumcodereview.appspot.com/19471009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@217417 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py14
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.h9
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc432
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h14
-rw-r--r--gpu/command_buffer/service/texture_manager.cc234
-rw-r--r--gpu/command_buffer/service/texture_manager.h81
6 files changed, 440 insertions, 344 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 6555da2..a6f13c1 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -62,13 +62,15 @@ _GL_TYPES = {
_CAPABILITY_FLAGS = [
{'name': 'blend'},
{'name': 'cull_face'},
- {'name': 'depth_test', 'state_flag': 'clear_state_dirty_'},
+ {'name': 'depth_test', 'state_flag': 'framebuffer_state_.clear_state_dirty'},
{'name': 'dither', 'default': True},
{'name': 'polygon_offset_fill'},
{'name': 'sample_alpha_to_coverage'},
{'name': 'sample_coverage'},
- {'name': 'scissor_test', 'state_flag': 'clear_state_dirty_'},
- {'name': 'stencil_test', 'state_flag': 'clear_state_dirty_'},
+ {'name': 'scissor_test',
+ 'state_flag': 'framebuffer_state_.clear_state_dirty'},
+ {'name': 'stencil_test',
+ 'state_flag': 'framebuffer_state_.clear_state_dirty'},
]
_STATES = {
@@ -101,7 +103,7 @@ _STATES = {
{'name': 'color_mask_blue', 'type': 'GLboolean', 'default': 'true'},
{'name': 'color_mask_alpha', 'type': 'GLboolean', 'default': 'true'},
],
- 'state_flag': 'clear_state_dirty_',
+ 'state_flag': 'framebuffer_state_.clear_state_dirty',
},
'ClearStencil': {
'type': 'Normal',
@@ -242,7 +244,7 @@ _STATES = {
'StencilMask': {
'type': 'FrontBack',
'func': 'StencilMaskSeparate',
- 'state_flag': 'clear_state_dirty_',
+ 'state_flag': 'framebuffer_state_.clear_state_dirty',
'states': [
{
'name': 'stencil_front_writemask',
@@ -400,7 +402,7 @@ _STATES = {
'states': [
{'name': 'depth_mask', 'type': 'GLboolean', 'default': 'true'},
],
- 'state_flag': 'clear_state_dirty_',
+ 'state_flag': 'framebuffer_state_.clear_state_dirty',
},
'Scissor': {
'type': 'Normal',
diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h
index 176e3e2..aa11118 100644
--- a/gpu/command_buffer/service/framebuffer_manager.h
+++ b/gpu/command_buffer/service/framebuffer_manager.h
@@ -180,6 +180,15 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> {
DISALLOW_COPY_AND_ASSIGN(Framebuffer);
};
+struct DecoderFramebufferState {
+ DecoderFramebufferState():
+ clear_state_dirty(true) {}
+
+ // State saved for clearing so we can clear render buffers and then
+ // restore to these values.
+ bool clear_state_dirty;
+};
+
// This class keeps track of the frambebuffers and their attached renderbuffers
// so we can correctly clear them.
class GPU_EXPORT FramebufferManager {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index a9b1f1e..44a0134 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -349,18 +349,6 @@ class ScopedResolvedFrameBufferBinder {
DISALLOW_COPY_AND_ASSIGN(ScopedResolvedFrameBufferBinder);
};
-// This class records texture upload time when in scope.
-class ScopedTextureUploadTimer {
- public:
- explicit ScopedTextureUploadTimer(GLES2DecoderImpl* decoder);
- ~ScopedTextureUploadTimer();
-
- private:
- GLES2DecoderImpl* decoder_;
- base::TimeTicks begin_time_;
- DISALLOW_COPY_AND_ASSIGN(ScopedTextureUploadTimer);
-};
-
// Encapsulates an OpenGL texture.
class BackTexture {
public:
@@ -651,7 +639,6 @@ class GLES2DecoderImpl : public GLES2Decoder {
friend class ScopedFrameBufferBinder;
friend class ScopedGLErrorSuppressor;
friend class ScopedResolvedFrameBufferBinder;
- friend class ScopedTextureUploadTimer;
friend class BackTexture;
friend class BackRenderbuffer;
friend class BackFramebuffer;
@@ -813,33 +800,6 @@ class GLES2DecoderImpl : public GLES2Decoder {
GLsizei width,
GLsizei height);
- // Validation for TexImage2D commands.
- bool ValidateTexImage2D(
- const char* function_name,
- GLenum target,
- GLint level,
- GLenum internal_format,
- GLsizei width,
- GLsizei height,
- GLint border,
- GLenum format,
- GLenum type,
- const void* pixels,
- uint32 pixels_size);
-
- // Wrapper for TexImage2D commands.
- void DoTexImage2D(
- GLenum target,
- GLint level,
- GLenum internal_format,
- GLsizei width,
- GLsizei height,
- GLint border,
- GLenum format,
- GLenum type,
- const void* pixels,
- uint32 pixels_size);
-
// Validation for TexSubImage2D.
bool ValidateTexSubImage2D(
error::Error* error,
@@ -1427,46 +1387,6 @@ class GLES2DecoderImpl : public GLES2Decoder {
bool instanced, GLenum mode, GLsizei count, GLenum type,
int32 offset, GLsizei primcount);
- // Gets the texture id for a given target.
- TextureRef* GetTextureInfoForTarget(GLenum target) {
- TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
- TextureRef* texture = NULL;
- switch (target) {
- case GL_TEXTURE_2D:
- texture = unit.bound_texture_2d.get();
- break;
- case GL_TEXTURE_CUBE_MAP:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- texture = unit.bound_texture_cube_map.get();
- break;
- case GL_TEXTURE_EXTERNAL_OES:
- texture = unit.bound_texture_external_oes.get();
- break;
- case GL_TEXTURE_RECTANGLE_ARB:
- texture = unit.bound_texture_rectangle_arb.get();
- break;
- default:
- NOTREACHED();
- return NULL;
- }
- return texture;
- }
-
- TextureRef* GetTextureInfoForTargetUnlessDefault(
- GLenum target) {
- TextureRef* texture = GetTextureInfoForTarget(target);
- if (!texture)
- return NULL;
- if (texture == texture_manager()->GetDefaultTextureInfo(target))
- return NULL;
- return texture;
- }
-
GLenum GetBindTargetForSamplerType(GLenum type) {
DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE ||
type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB);
@@ -1642,10 +1562,6 @@ class GLES2DecoderImpl : public GLES2Decoder {
// The size of fiixed attrib buffer.
GLsizei fixed_attrib_buffer_size_;
- // state saved for clearing so we can clear render buffers and then
- // restore to these values.
- bool clear_state_dirty_;
-
// 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_.
@@ -1692,8 +1608,6 @@ class GLES2DecoderImpl : public GLES2Decoder {
// Backbuffer attachments that are currently undefined.
uint32 backbuffer_needs_clear_bits_;
- bool teximage2d_faster_than_texsubimage2d_;
-
// The current decoder error.
error::Error current_decoder_error_;
@@ -1707,10 +1621,6 @@ class GLES2DecoderImpl : public GLES2Decoder {
const Validators* validators_;
scoped_refptr<FeatureInfo> feature_info_;
- // This indicates all the following texSubImage2D calls that are part of the
- // failed texImage2D call should be ignored.
- bool tex_image_2d_failed_;
-
int frame_number_;
bool has_robustness_extension_;
@@ -1744,10 +1654,12 @@ class GLES2DecoderImpl : public GLES2Decoder {
GLsizei viewport_max_height_;
// Command buffer stats.
- int texture_upload_count_;
- base::TimeDelta total_texture_upload_time_;
base::TimeDelta total_processing_commands_time_;
+ // States related to each manager.
+ DecoderTextureState texture_state_;
+ DecoderFramebufferState framebuffer_state_;
+
scoped_ptr<GPUTracer> gpu_tracer_;
std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
@@ -1881,17 +1793,6 @@ ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
}
}
-ScopedTextureUploadTimer::ScopedTextureUploadTimer(GLES2DecoderImpl* decoder)
- : decoder_(decoder),
- begin_time_(base::TimeTicks::HighResNow()) {
-}
-
-ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
- decoder_->texture_upload_count_++;
- decoder_->total_texture_upload_time_ +=
- base::TimeTicks::HighResNow() - begin_time_;
-}
-
BackTexture::BackTexture(GLES2DecoderImpl* decoder)
: decoder_(decoder),
memory_tracker_(decoder->memory_tracker(), MemoryTracker::kUnmanaged),
@@ -2156,7 +2057,6 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
attrib_0_size_(0),
fixed_attrib_buffer_id_(0),
fixed_attrib_buffer_size_(0),
- clear_state_dirty_(true),
offscreen_target_color_format_(0),
offscreen_target_depth_format_(0),
offscreen_target_stencil_format_(0),
@@ -2167,12 +2067,10 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
back_buffer_has_depth_(false),
back_buffer_has_stencil_(false),
backbuffer_needs_clear_bits_(0),
- teximage2d_faster_than_texsubimage2d_(true),
current_decoder_error_(error::kNoError),
use_shader_translator_(true),
validators_(group_->feature_info()->validators()),
feature_info_(group_->feature_info()),
- tex_image_2d_failed_(false),
frame_number_(0),
has_robustness_extension_(false),
reset_status_(GL_NO_ERROR),
@@ -2185,8 +2083,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableGPUServiceLoggingGPU)),
viewport_max_width_(0),
- viewport_max_height_(0),
- texture_upload_count_(0) {
+ viewport_max_height_(0) {
DCHECK(group);
attrib_0_value_.v[0] = 0.0f;
@@ -2207,7 +2104,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
// TODO(gman): Consider setting this based on GPU and/or driver.
if (IsAngle()) {
- teximage2d_faster_than_texsubimage2d_ = false;
+ texture_state_.teximage2d_faster_than_texsubimage2d = false;
}
}
@@ -2717,7 +2614,7 @@ void GLES2DecoderImpl::DeleteFramebuffersHelper(
if (framebuffer && !framebuffer->IsDeleted()) {
if (framebuffer == state_.bound_draw_framebuffer.get()) {
state_.bound_draw_framebuffer = NULL;
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
GLenum target = supports_separate_framebuffer_binds ?
GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
glBindFramebufferEXT(target, GetBackbufferServiceId());
@@ -2761,7 +2658,7 @@ void GLES2DecoderImpl::DeleteRenderbuffersHelper(
->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
}
}
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
RemoveRenderbuffer(client_ids[ii]);
}
}
@@ -2776,7 +2673,7 @@ void GLES2DecoderImpl::DeleteTexturesHelper(
if (texture_ref) {
Texture* texture = texture_ref->texture();
if (texture->IsAttachedToFramebuffer()) {
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
}
// Unbind texture_ref from texture_ref units.
for (size_t jj = 0; jj < state_.texture_units.size(); ++jj) {
@@ -2835,7 +2732,7 @@ bool GLES2DecoderImpl::MakeCurrent() {
if (workarounds().unbind_fbo_on_context_switch)
RestoreFramebufferBindings();
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
return true;
}
@@ -2879,7 +2776,7 @@ static void RebindCurrentFramebuffer(
}
void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
if (!features().chromium_framebuffer_multisample) {
RebindCurrentFramebuffer(
@@ -3075,7 +2972,8 @@ void GLES2DecoderImpl::UpdateParentTextureInfo() {
offscreen_saved_color_texture_info_.get(),
GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
glBindTexture(target, texture_ref ? texture_ref->service_id() : 0);
}
@@ -3127,12 +3025,12 @@ bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
}
uint32 GLES2DecoderImpl::GetTextureUploadCount() {
- return texture_upload_count_ +
+ return texture_state_.texture_upload_count +
async_pixel_transfer_manager_->GetTextureUploadCount();
}
base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
- return total_texture_upload_time_ +
+ return texture_state_.total_texture_upload_time +
async_pixel_transfer_manager_->GetTotalTextureUploadTime();
}
@@ -3678,7 +3576,7 @@ bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
}
void GLES2DecoderImpl::ApplyDirtyState() {
- if (clear_state_dirty_) {
+ if (framebuffer_state_.clear_state_dirty) {
glColorMask(
state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
state_.color_mask_alpha &&
@@ -3696,7 +3594,7 @@ void GLES2DecoderImpl::ApplyDirtyState() {
EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
EnableDisable(GL_BLEND, state_.enable_flags.blend);
- clear_state_dirty_ = false;
+ framebuffer_state_.clear_state_dirty = false;
}
}
@@ -3804,7 +3702,7 @@ void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
state_.bound_read_framebuffer = framebuffer;
}
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
// If we are rendering to the backbuffer get the FBO id for any simulated
// backbuffer.
@@ -3982,7 +3880,8 @@ void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
}
void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
if (!texture_ref ||
!texture_manager()->CanGenerateMipmaps(texture_ref)) {
LOCAL_SET_GL_ERROR(
@@ -4758,7 +4657,7 @@ void GLES2DecoderImpl::DoFramebufferRenderbuffer(
framebuffer->AttachRenderbuffer(attachment, renderbuffer);
}
if (framebuffer == state_.bound_draw_framebuffer.get()) {
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
}
OnFboChanged();
}
@@ -4842,7 +4741,7 @@ void GLES2DecoderImpl::ClearUnclearedAttachments(
}
void GLES2DecoderImpl::RestoreClearState() {
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
glClearColor(
state_.color_clear_red, state_.color_clear_green, state_.color_clear_blue,
state_.color_clear_alpha);
@@ -4942,7 +4841,7 @@ void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
samples);
}
if (framebuffer == state_.bound_draw_framebuffer.get()) {
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
}
OnFboChanged();
}
@@ -5181,7 +5080,8 @@ void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
void GLES2DecoderImpl::DoTexParameterf(
GLenum target, GLenum pname, GLfloat param) {
- TextureRef* texture = GetTextureInfoForTarget(target);
+ TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
if (!texture) {
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterf", "unknown texture");
return;
@@ -5194,7 +5094,8 @@ void GLES2DecoderImpl::DoTexParameterf(
void GLES2DecoderImpl::DoTexParameteri(
GLenum target, GLenum pname, GLint param) {
- TextureRef* texture = GetTextureInfoForTarget(target);
+ TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
if (!texture) {
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
return;
@@ -5206,7 +5107,8 @@ void GLES2DecoderImpl::DoTexParameteri(
void GLES2DecoderImpl::DoTexParameterfv(
GLenum target, GLenum pname, const GLfloat* params) {
- TextureRef* texture = GetTextureInfoForTarget(target);
+ TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
if (!texture) {
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameterfv", "unknown texture");
return;
@@ -5219,7 +5121,8 @@ void GLES2DecoderImpl::DoTexParameterfv(
void GLES2DecoderImpl::DoTexParameteriv(
GLenum target, GLenum pname, const GLint* params) {
- TextureRef* texture = GetTextureInfoForTarget(target);
+ TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
if (!texture) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE, "glTexParameteriv", "unknown texture");
@@ -7420,7 +7323,8 @@ bool GLES2DecoderImpl::ClearLevel(
}
y += tile_height;
}
- TextureRef* texture = GetTextureInfoForTarget(bind_target);
+ TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
+ &state_, bind_target);
glBindTexture(bind_target, texture ? texture->service_id() : 0);
return true;
}
@@ -7595,7 +7499,8 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
"glCompressedTexImage2D", "dimensions out of range");
return error::kNoError;
}
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE,
@@ -7624,7 +7529,7 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
}
if (texture->IsAttachedToFramebuffer()) {
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
}
scoped_ptr<int8[]> zero;
@@ -7759,176 +7664,16 @@ error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DBucket(
return error::kNoError;
}
-bool GLES2DecoderImpl::ValidateTextureParameters(
- const char* function_name,
- GLenum target, GLenum format, GLenum type, GLint level) {
- if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, function_name,
- (std::string("invalid type ") +
- GLES2Util::GetStringEnum(type) + " for format " +
- GLES2Util::GetStringEnum(format)).c_str());
- return false;
- }
-
- uint32 channels = GLES2Util::GetChannelsForFormat(format);
- if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, function_name,
- (std::string("invalid type ") +
- GLES2Util::GetStringEnum(type) + " for format " +
- GLES2Util::GetStringEnum(format)).c_str());
- return false;
- }
- return true;
-}
-
-bool GLES2DecoderImpl::ValidateTexImage2D(
- const char* function_name,
- GLenum target,
- GLint level,
- GLenum internal_format,
- GLsizei width,
- GLsizei height,
- GLint border,
- GLenum format,
- GLenum type,
- const void* pixels,
- uint32 pixels_size) {
- if (!validators_->texture_target.IsValid(target)) {
- LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
- return false;
- }
- if (!validators_->texture_format.IsValid(internal_format)) {
- LOCAL_SET_GL_ERROR_INVALID_ENUM(
- function_name, internal_format, "internal_format");
- return false;
- }
- if (!validators_->texture_format.IsValid(format)) {
- LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
- return false;
- }
- if (!validators_->pixel_type.IsValid(type)) {
- LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
- return false;
- }
- if (format != internal_format) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, function_name, "format != internalFormat");
- return false;
- }
- if (!ValidateTextureParameters(function_name, target, format, type, level)) {
- return false;
- }
- if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
- border != 0) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_VALUE, function_name, "dimensions out of range");
- return false;
- }
- if ((GLES2Util::GetChannelsForFormat(format) &
- (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && pixels) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- function_name, "can not supply data for depth or stencil textures");
- return false;
- }
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
- if (!texture_ref) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, function_name, "unknown texture for target");
- return false;
- }
- if (texture_ref->texture()->IsImmutable()) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, function_name, "texture is immutable");
- return false;
- }
- return true;
-}
-
-void GLES2DecoderImpl::DoTexImage2D(
- GLenum target,
- GLint level,
- GLenum internal_format,
- GLsizei width,
- GLsizei height,
- GLint border,
- GLenum format,
- GLenum type,
- const void* pixels,
- uint32 pixels_size) {
- if (!ValidateTexImage2D("glTexImage2D", target, level, internal_format,
- width, height, border, format, type, pixels, pixels_size)) {
- return;
- }
-
- if (!EnsureGPUMemoryAvailable(pixels_size)) {
- LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexImage2D", "out of memory");
- return;
- }
-
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
- Texture* texture = texture_ref->texture();
- GLsizei tex_width = 0;
- GLsizei tex_height = 0;
- GLenum tex_type = 0;
- GLenum tex_format = 0;
- bool level_is_same =
- texture->GetLevelSize(target, level, &tex_width, &tex_height) &&
- texture->GetLevelType(target, level, &tex_type, &tex_format) &&
- width == tex_width && height == tex_height &&
- type == tex_type && format == tex_format;
-
- if (level_is_same && !pixels) {
- // Just set the level texture but mark the texture as uncleared.
- texture_manager()->SetLevelInfo(
- texture_ref,
- target, level, internal_format, width, height, 1, border, format, type,
- false);
- tex_image_2d_failed_ = false;
- return;
- }
-
- if (texture->IsAttachedToFramebuffer()) {
- clear_state_dirty_ = true;
- }
-
- if (!teximage2d_faster_than_texsubimage2d_ && level_is_same && pixels) {
- {
- ScopedTextureUploadTimer timer(this);
- glTexSubImage2D(target, level, 0, 0, width, height, format, type, pixels);
- }
- texture_manager()->SetLevelCleared(texture_ref, target, level, true);
- tex_image_2d_failed_ = false;
- return;
- }
-
- LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexImage2D");
- {
- ScopedTextureUploadTimer timer(this);
- glTexImage2D(
- target, level, internal_format, width, height, border, format, type,
- pixels);
- }
- GLenum error = LOCAL_PEEK_GL_ERROR("glTexImage2D");
- if (error == GL_NO_ERROR) {
- texture_manager()->SetLevelInfo(
- texture_ref,
- target, level, internal_format, width, height, 1, border, format, type,
- pixels != NULL);
- tex_image_2d_failed_ = false;
- }
- return;
-}
-
error::Error GLES2DecoderImpl::HandleTexImage2D(
uint32 immediate_data_size, const cmds::TexImage2D& c) {
TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexImage2D");
- tex_image_2d_failed_ = true;
+ // Set as failed for now, but if it successed, this will be set to not failed.
+ texture_state_.tex_image_2d_failed = true;
GLenum target = static_cast<GLenum>(c.target);
GLint level = static_cast<GLint>(c.level);
- GLint internal_format = static_cast<GLint>(c.internalformat);
+ // TODO(kloveless): Change TexImage2D command to use unsigned integer
+ // for internalformat.
+ GLenum internal_format = static_cast<GLenum>(c.internalformat);
GLsizei width = static_cast<GLsizei>(c.width);
GLsizei height = static_cast<GLsizei>(c.height);
GLint border = static_cast<GLint>(c.border);
@@ -7951,9 +7696,11 @@ error::Error GLES2DecoderImpl::HandleTexImage2D(
}
}
- DoTexImage2D(
- target, level, internal_format, width, height, border, format, type,
- pixels, pixels_size);
+ TextureManager::DoTextImage2DArguments args = {
+ target, level, internal_format, width, height, border, format, type,
+ pixels, pixels_size};
+ texture_manager()->ValidateAndDoTexImage2D(
+ &texture_state_, &state_, &framebuffer_state_, args);
return error::kNoError;
}
@@ -7961,7 +7708,9 @@ error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
uint32 immediate_data_size, const cmds::TexImage2DImmediate& c) {
GLenum target = static_cast<GLenum>(c.target);
GLint level = static_cast<GLint>(c.level);
- GLint internal_format = static_cast<GLint>(c.internalformat);
+ // TODO(kloveless): Change TexImage2DImmediate command to use unsigned
+ // integer for internalformat.
+ GLenum internal_format = static_cast<GLenum>(c.internalformat);
GLsizei width = static_cast<GLsizei>(c.width);
GLsizei height = static_cast<GLsizei>(c.height);
GLint border = static_cast<GLint>(c.border);
@@ -7978,9 +7727,12 @@ error::Error GLES2DecoderImpl::HandleTexImage2DImmediate(
if (!pixels) {
return error::kOutOfBounds;
}
- DoTexImage2D(
- target, level, internal_format, width, height, border, format, type,
- pixels, size);
+
+ TextureManager::DoTextImage2DArguments args = {
+ target, level, internal_format, width, height, border, format, type,
+ pixels, size};
+ texture_manager()->ValidateAndDoTexImage2D(
+ &texture_state_, &state_, &framebuffer_state_, args);
return error::kNoError;
}
@@ -7994,7 +7746,8 @@ void GLES2DecoderImpl::DoCompressedTexSubImage2D(
GLenum format,
GLsizei image_size,
const void * data) {
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -8067,7 +7820,8 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
GLsizei height,
GLint border) {
DCHECK(!ShouldDeferReads());
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -8085,8 +7839,9 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
return;
}
- if (!ValidateTextureParameters(
- "glCopyTexImage2D", target, internal_format, GL_UNSIGNED_BYTE, level)) {
+ if (!texture_manager()->ValidateTextureParameters(
+ state_.GetErrorState(), "glCopyTexImage2D", target, internal_format,
+ GL_UNSIGNED_BYTE, level)) {
return;
}
@@ -8131,7 +7886,7 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
gfx::Size size = GetBoundReadFrameBufferSize();
if (texture->IsAttachedToFramebuffer()) {
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
}
// Clip to size to source dimensions
@@ -8186,7 +7941,8 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D(
GLsizei width,
GLsizei height) {
DCHECK(!ShouldDeferReads());
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -8312,7 +8068,8 @@ bool GLES2DecoderImpl::ValidateTexSubImage2D(
LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
return false;
}
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -8379,7 +8136,8 @@ error::Error GLES2DecoderImpl::DoTexSubImage2D(
xoffset, yoffset, width, height, format, type, data)) {
return error;
}
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
Texture* texture = texture_ref->texture();
GLsizei tex_width = 0;
GLsizei tex_height = 0;
@@ -8393,20 +8151,21 @@ error::Error GLES2DecoderImpl::DoTexSubImage2D(
GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
return error::kNoError;
}
- ScopedTextureUploadTimer timer(this);
+ ScopedTextureUploadTimer timer(&texture_state_);
glTexSubImage2D(
target, level, xoffset, yoffset, width, height, format, type, data);
return error::kNoError;
}
- if (teximage2d_faster_than_texsubimage2d_ && !texture->IsImmutable()) {
- ScopedTextureUploadTimer timer(this);
+ if (texture_state_.teximage2d_faster_than_texsubimage2d &&
+ !texture->IsImmutable()) {
+ ScopedTextureUploadTimer timer(&texture_state_);
// NOTE: In OpenGL ES 2.0 border is always zero and format is always the
// same as internal_foramt. If that changes we'll need to look them up.
glTexImage2D(
target, level, format, width, height, 0, format, type, data);
} else {
- ScopedTextureUploadTimer timer(this);
+ ScopedTextureUploadTimer timer(&texture_state_);
glTexSubImage2D(
target, level, xoffset, yoffset, width, height, format, type, data);
}
@@ -8418,7 +8177,7 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D(
uint32 immediate_data_size, const cmds::TexSubImage2D& c) {
TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleTexSubImage2D");
GLboolean internal = static_cast<GLboolean>(c.internal);
- if (internal == GL_TRUE && tex_image_2d_failed_)
+ if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
return error::kNoError;
GLenum target = static_cast<GLenum>(c.target);
@@ -8444,7 +8203,7 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D(
error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
uint32 immediate_data_size, const cmds::TexSubImage2DImmediate& c) {
GLboolean internal = static_cast<GLboolean>(c.internal);
- if (internal == GL_TRUE && tex_image_2d_failed_)
+ if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
return error::kNoError;
GLenum target = static_cast<GLenum>(c.target);
@@ -9564,7 +9323,8 @@ void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM(
// Default target might be conceptually valid, but disallow it to avoid
// accidents.
- TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
+ TextureRef* texture_ref =
+ texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -9879,7 +9639,8 @@ void GLES2DecoderImpl::DoTexStorage2DEXT(
GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
return;
}
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -9888,7 +9649,7 @@ void GLES2DecoderImpl::DoTexStorage2DEXT(
}
Texture* texture = texture_ref->texture();
if (texture->IsAttachedToFramebuffer()) {
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
}
if (texture->IsImmutable()) {
LOCAL_SET_GL_ERROR(
@@ -9960,7 +9721,8 @@ void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
"context", logger_.GetLogPrefix(),
"mailbox[0]", static_cast<unsigned char>(mailbox[0]));
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -9994,7 +9756,7 @@ void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
"mailbox[0]", static_cast<unsigned char>(mailbox[0]));
scoped_refptr<TextureRef> texture_ref =
- GetTextureInfoForTargetUnlessDefault(target);
+ texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
if (!texture_ref.get()) {
LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
"glConsumeTextureCHROMIUM",
@@ -10085,7 +9847,8 @@ void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
// Default target might be conceptually valid, but disallow it to avoid
// accidents.
- TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
+ TextureRef* texture_ref =
+ texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -10132,7 +9895,8 @@ void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
// Default target might be conceptually valid, but disallow it to avoid
// accidents.
- TextureRef* texture_ref = GetTextureInfoForTargetUnlessDefault(target);
+ TextureRef* texture_ref =
+ texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
@@ -10273,7 +10037,9 @@ error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
GLenum target = static_cast<GLenum>(c.target);
GLint level = static_cast<GLint>(c.level);
- GLint internal_format = static_cast<GLint>(c.internalformat);
+ // TODO(kloveless): Change HandleAsyncTexImage2DCHROMIUM command to use
+ // unsigned integer for internalformat.
+ GLenum internal_format = static_cast<GLenum>(c.internalformat);
GLsizei width = static_cast<GLsizei>(c.width);
GLsizei height = static_cast<GLsizei>(c.height);
GLint border = static_cast<GLint>(c.border);
@@ -10299,15 +10065,17 @@ error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
}
}
+ TextureManager::DoTextImage2DArguments args = {
+ target, level, internal_format, width, height, border, format, type,
+ pixels, pixels_size};
+ TextureRef* texture_ref;
// All the normal glTexSubImage2D validation.
- if (!ValidateTexImage2D(
- "glAsyncTexImage2DCHROMIUM", target, level, internal_format,
- width, height, border, format, type, pixels, pixels_size)) {
+ if (!texture_manager()->ValidateTexImage2D(
+ &state_, "glAsyncTexImage2DCHROMIUM", args, &texture_ref)) {
return error::kNoError;
}
// Extra async validation.
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
Texture* texture = texture_ref->texture();
if (!ValidateAsyncTransfer(
"glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
@@ -10394,7 +10162,8 @@ error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
}
// Extra async validation.
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
Texture* texture = texture_ref->texture();
if (!ValidateAsyncTransfer(
"glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
@@ -10462,7 +10231,8 @@ error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
GL_INVALID_ENUM, "glWaitAsyncTexImage2DCHROMIUM", "target");
return error::kNoError;
}
- TextureRef* texture_ref = GetTextureInfoForTarget(target);
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index a992e34..393c902 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -319,7 +319,7 @@ error::Error GLES2DecoderImpl::HandleColorMask(
state_.color_mask_green = green;
state_.color_mask_blue = blue;
state_.color_mask_alpha = alpha;
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
}
return error::kNoError;
}
@@ -678,7 +678,7 @@ error::Error GLES2DecoderImpl::HandleDepthMask(
GLboolean flag = static_cast<GLboolean>(c.flag);
if (state_.depth_mask != flag) {
state_.depth_mask = flag;
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
}
return error::kNoError;
}
@@ -1698,7 +1698,7 @@ error::Error GLES2DecoderImpl::HandleStencilMask(
state_.stencil_back_writemask != mask) {
state_.stencil_front_writemask = mask;
state_.stencil_back_writemask = mask;
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
}
return error::kNoError;
}
@@ -1725,7 +1725,7 @@ error::Error GLES2DecoderImpl::HandleStencilMaskSeparate(
if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
state_.stencil_back_writemask = mask;
}
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
}
return error::kNoError;
}
@@ -3332,7 +3332,7 @@ bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
case GL_DEPTH_TEST:
if (state_.enable_flags.depth_test != enabled) {
state_.enable_flags.depth_test = enabled;
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
}
return false;
case GL_DITHER:
@@ -3350,13 +3350,13 @@ bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
case GL_SCISSOR_TEST:
if (state_.enable_flags.scissor_test != enabled) {
state_.enable_flags.scissor_test = enabled;
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
}
return false;
case GL_STENCIL_TEST:
if (state_.enable_flags.stencil_test != enabled) {
state_.enable_flags.stencil_test = enabled;
- clear_state_dirty_ = true;
+ framebuffer_state_.clear_state_dirty = true;
}
return false;
default:
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index 486bdac..deb8c8e 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -6,6 +6,7 @@
#include "base/bits.h"
#include "base/strings/stringprintf.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/service/context_state.h"
#include "gpu/command_buffer/service/error_state.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/framebuffer_manager.h"
@@ -1236,5 +1237,238 @@ void TextureManager::IncFramebufferStateChangeCount() {
}
+bool TextureManager::ValidateTextureParameters(
+ ErrorState* error_state, const char* function_name,
+ GLenum target, GLenum format, GLenum type, GLint level) {
+ if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ (std::string("invalid type ") +
+ GLES2Util::GetStringEnum(type) + " for format " +
+ GLES2Util::GetStringEnum(format)).c_str());
+ return false;
+ }
+
+ uint32 channels = GLES2Util::GetChannelsForFormat(format);
+ if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ (std::string("invalid type ") +
+ GLES2Util::GetStringEnum(type) + " for format " +
+ GLES2Util::GetStringEnum(format)).c_str());
+ return false;
+ }
+ return true;
+}
+
+// Gets the texture id for a given target.
+TextureRef* TextureManager::GetTextureInfoForTarget(
+ ContextState* state, GLenum target) {
+ TextureUnit& unit = state->texture_units[state->active_texture_unit];
+ TextureRef* texture = NULL;
+ switch (target) {
+ case GL_TEXTURE_2D:
+ texture = unit.bound_texture_2d.get();
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ texture = unit.bound_texture_cube_map.get();
+ break;
+ case GL_TEXTURE_EXTERNAL_OES:
+ texture = unit.bound_texture_external_oes.get();
+ break;
+ case GL_TEXTURE_RECTANGLE_ARB:
+ texture = unit.bound_texture_rectangle_arb.get();
+ break;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+ return texture;
+}
+
+TextureRef* TextureManager::GetTextureInfoForTargetUnlessDefault(
+ ContextState* state, GLenum target) {
+ TextureRef* texture = GetTextureInfoForTarget(state, target);
+ if (!texture)
+ return NULL;
+ if (texture == GetDefaultTextureInfo(target))
+ return NULL;
+ return texture;
+}
+
+bool TextureManager::ValidateTexImage2D(
+ ContextState* state,
+ const char* function_name,
+ const DoTextImage2DArguments& args,
+ TextureRef** texture_ref) {
+ ErrorState* error_state = state->GetErrorState();
+ const Validators* validators = feature_info_->validators();
+ if (!validators->texture_target.IsValid(args.target)) {
+ ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
+ error_state, function_name, args.target, "target");
+ return false;
+ }
+ if (!validators->texture_format.IsValid(args.internal_format)) {
+ ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
+ error_state, function_name, args.internal_format,
+ "internal_format");
+ return false;
+ }
+ if (!validators->texture_format.IsValid(args.format)) {
+ ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
+ error_state, function_name, args.format, "format");
+ return false;
+ }
+ if (!validators->pixel_type.IsValid(args.type)) {
+ ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
+ error_state, function_name, args.type, "type");
+ return false;
+ }
+ if (args.format != args.internal_format) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ "format != internalFormat");
+ return false;
+ }
+ if (!ValidateTextureParameters(
+ error_state, function_name, args.target, args.format, args.type,
+ args.level)) {
+ return false;
+ }
+ if (!ValidForTarget(args.target, args.level, args.width, args.height, 1) ||
+ args.border != 0) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_VALUE, function_name,
+ "dimensions out of range");
+ return false;
+ }
+ if ((GLES2Util::GetChannelsForFormat(args.format) &
+ (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && args.pixels) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION,
+ function_name, "can not supply data for depth or stencil textures");
+ return false;
+ }
+
+ TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target);
+ if (!local_texture_ref) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ "unknown texture for target");
+ return false;
+ }
+ if (local_texture_ref->texture()->IsImmutable()) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ "texture is immutable");
+ return false;
+ }
+
+ // TODO - verify that using the managed vs unmanaged does not matter.
+ // They both use the same MemoryTracker, and this call just re-routes
+ // to it.
+ if (!memory_tracker_managed_->EnsureGPUMemoryAvailable(args.pixels_size)) {
+ ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, "glTexImage2D",
+ "out of memory");
+ return false;
+ }
+
+ // Write the TextureReference since this is valid.
+ *texture_ref = local_texture_ref;
+ return true;
+}
+
+void TextureManager::ValidateAndDoTexImage2D(
+ DecoderTextureState* texture_state,
+ ContextState* state,
+ DecoderFramebufferState* framebuffer_state,
+ const DoTextImage2DArguments& args) {
+ TextureRef* texture_ref;
+ if (!ValidateTexImage2D(state, "glTexImage2D", args, &texture_ref)) {
+ return;
+ }
+
+ DoTexImage2D(texture_state, state->GetErrorState(), framebuffer_state,
+ texture_ref, args);
+}
+
+void TextureManager::DoTexImage2D(
+ DecoderTextureState* texture_state,
+ ErrorState* error_state,
+ DecoderFramebufferState* framebuffer_state,
+ TextureRef* texture_ref,
+ const DoTextImage2DArguments& args) {
+ Texture* texture = texture_ref->texture();
+ GLsizei tex_width = 0;
+ GLsizei tex_height = 0;
+ GLenum tex_type = 0;
+ GLenum tex_format = 0;
+ bool level_is_same =
+ texture->GetLevelSize(args.target, args.level, &tex_width, &tex_height) &&
+ texture->GetLevelType(args.target, args.level, &tex_type, &tex_format) &&
+ args.width == tex_width && args.height == tex_height &&
+ args.type == tex_type && args.format == tex_format;
+
+ if (level_is_same && !args.pixels) {
+ // Just set the level texture but mark the texture as uncleared.
+ SetLevelInfo(
+ texture_ref,
+ args.target, args.level, args.internal_format, args.width, args.height,
+ 1, args.border, args.format, args.type, false);
+ texture_state->tex_image_2d_failed = false;
+ return;
+ }
+
+ if (texture->IsAttachedToFramebuffer()) {
+ framebuffer_state->clear_state_dirty = true;
+ }
+
+ if (!texture_state->teximage2d_faster_than_texsubimage2d &&
+ level_is_same && args.pixels) {
+ {
+ ScopedTextureUploadTimer timer(texture_state);
+ glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height,
+ args.format, args.type, args.pixels);
+ }
+ SetLevelCleared(texture_ref, args.target, args.level, true);
+ texture_state->tex_image_2d_failed = false;
+ return;
+ }
+
+ ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glTexImage2D");
+ {
+ ScopedTextureUploadTimer timer(texture_state);
+ glTexImage2D(
+ args.target, args.level, args.internal_format, args.width, args.height,
+ args.border, args.format, args.type, args.pixels);
+ }
+ GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glTexImage2D");
+ if (error == GL_NO_ERROR) {
+ SetLevelInfo(
+ texture_ref,
+ args.target, args.level, args.internal_format, args.width, args.height,
+ 1, args.border, args.format, args.type, args.pixels != NULL);
+ texture_state->tex_image_2d_failed = false;
+ }
+}
+
+ScopedTextureUploadTimer::ScopedTextureUploadTimer(
+ DecoderTextureState* texture_state)
+ : texture_state_(texture_state),
+ begin_time_(base::TimeTicks::HighResNow()) {
+}
+
+ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
+ texture_state_->texture_upload_count++;
+ texture_state_->total_texture_upload_time +=
+ base::TimeTicks::HighResNow() - begin_time_;
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index cbc659c..db47004 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -27,6 +27,8 @@ class StreamTextureManager;
namespace gles2 {
class GLES2Decoder;
+struct ContextState;
+struct DecoderFramebufferState;
class Display;
class ErrorState;
class FeatureInfo;
@@ -429,6 +431,29 @@ class GPU_EXPORT TextureRef : public base::RefCounted<TextureRef> {
DISALLOW_COPY_AND_ASSIGN(TextureRef);
};
+// Holds data that is per gles2_cmd_decoder, but is related to to the
+// TextureManager.
+struct DecoderTextureState {
+ // total_texture_upload_time automatically initialized to 0 in default
+ // constructor.
+ DecoderTextureState():
+ tex_image_2d_failed(false),
+ texture_upload_count(0),
+ teximage2d_faster_than_texsubimage2d(true) {}
+
+ // This indicates all the following texSubImage2D calls that are part of the
+ // failed texImage2D call should be ignored.
+ bool tex_image_2d_failed;
+
+ // Command buffer stats.
+ int texture_upload_count;
+ base::TimeDelta total_texture_upload_time;
+
+ // This is really not per-decoder, but the logic to decide this value is in
+ // the decoder for now, so it is simpler to leave it there.
+ bool teximage2d_faster_than_texsubimage2d;
+};
+
// This class keeps track of the textures and their sizes so we can do NPOT and
// texture complete checking.
//
@@ -671,6 +696,43 @@ class GPU_EXPORT TextureManager {
destruction_observers_.RemoveObserver(observer);
}
+ struct DoTextImage2DArguments {
+ GLenum target;
+ GLint level;
+ GLenum internal_format;
+ GLsizei width;
+ GLsizei height;
+ GLint border;
+ GLenum format;
+ GLenum type;
+ const void* pixels;
+ uint32 pixels_size;
+ };
+
+ bool ValidateTexImage2D(
+ ContextState* state,
+ const char* function_name,
+ const DoTextImage2DArguments& args,
+ // Pointer to TextureRef filled in if validation successful.
+ // Presumes the pointer is valid.
+ TextureRef** texture_ref);
+
+ void ValidateAndDoTexImage2D(
+ DecoderTextureState* texture_state,
+ ContextState* state,
+ DecoderFramebufferState* framebuffer_state,
+ const DoTextImage2DArguments& args);
+
+ // TODO(kloveless): Make GetTexture* private once this is no longer called
+ // from gles2_cmd_decoder.
+ TextureRef* GetTextureInfoForTarget(ContextState* state, GLenum target);
+ TextureRef* GetTextureInfoForTargetUnlessDefault(
+ ContextState* state, GLenum target);
+
+ bool ValidateTextureParameters(
+ ErrorState* error_state, const char* function_name,
+ GLenum target, GLenum format, GLenum type, GLint level);
+
private:
friend class Texture;
friend class TextureRef;
@@ -680,6 +742,13 @@ class GPU_EXPORT TextureManager {
GLenum target,
GLuint* black_texture);
+ void DoTexImage2D(
+ DecoderTextureState* texture_state,
+ ErrorState* error_state,
+ DecoderFramebufferState* framebuffer_state,
+ TextureRef* texture_ref,
+ const DoTextImage2DArguments& args);
+
void StartTracking(TextureRef* texture);
void StopTracking(TextureRef* texture);
@@ -730,6 +799,18 @@ class GPU_EXPORT TextureManager {
DISALLOW_COPY_AND_ASSIGN(TextureManager);
};
+// This class records texture upload time when in scope.
+class ScopedTextureUploadTimer {
+ public:
+ explicit ScopedTextureUploadTimer(DecoderTextureState* texture_state);
+ ~ScopedTextureUploadTimer();
+
+ private:
+ DecoderTextureState* texture_state_;
+ base::TimeTicks begin_time_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedTextureUploadTimer);
+};
+
} // namespace gles2
} // namespace gpu