summaryrefslogtreecommitdiff
path: root/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc')
-rw-r--r--chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc1196
1 files changed, 701 insertions, 495 deletions
diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 120359ceae8..c2fcee2933a 100644
--- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -14,15 +14,12 @@
#include <vector>
#include "base/at_exit.h"
-#include "base/atomicops.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
-#if defined(OS_MACOSX)
-#include "base/mac/scoped_cftyperef.h"
-#endif
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
#include "build/build_config.h"
#define GLES2_GPU_SERVICE 1
#include "gpu/command_buffer/common/debug_marker_manager.h"
@@ -292,11 +289,11 @@ static void EnableDisable(GLenum pname, bool enable) {
class ScopedGLErrorSuppressor {
public:
explicit ScopedGLErrorSuppressor(
- const char* function_name, GLES2DecoderImpl* decoder);
+ const char* function_name, ErrorState* error_state);
~ScopedGLErrorSuppressor();
private:
const char* function_name_;
- GLES2DecoderImpl* decoder_;
+ ErrorState* error_state_;
DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
};
@@ -305,11 +302,11 @@ class ScopedGLErrorSuppressor {
// unit zero in case the client has changed that to something invalid.
class ScopedTexture2DBinder {
public:
- ScopedTexture2DBinder(GLES2DecoderImpl* decoder, GLuint id);
+ ScopedTexture2DBinder(ContextState* state, GLuint id);
~ScopedTexture2DBinder();
private:
- GLES2DecoderImpl* decoder_;
+ ContextState* state_;
DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
};
@@ -317,11 +314,11 @@ class ScopedTexture2DBinder {
// object goes out of scope.
class ScopedRenderBufferBinder {
public:
- ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, GLuint id);
+ ScopedRenderBufferBinder(ContextState* state, GLuint id);
~ScopedRenderBufferBinder();
private:
- GLES2DecoderImpl* decoder_;
+ ContextState* state_;
DISALLOW_COPY_AND_ASSIGN(ScopedRenderBufferBinder);
};
@@ -357,7 +354,7 @@ class ScopedResolvedFrameBufferBinder {
// Encapsulates an OpenGL texture.
class BackTexture {
public:
- explicit BackTexture(GLES2DecoderImpl* decoder);
+ explicit BackTexture(MemoryTracker* memory_tracker, ContextState* state);
~BackTexture();
// Create a new render texture.
@@ -390,8 +387,8 @@ class BackTexture {
}
private:
- GLES2DecoderImpl* decoder_;
MemoryTypeTracker memory_tracker_;
+ ContextState* state_;
size_t bytes_allocated_;
GLuint id_;
gfx::Size size_;
@@ -401,14 +398,20 @@ class BackTexture {
// Encapsulates an OpenGL render buffer of any format.
class BackRenderbuffer {
public:
- explicit BackRenderbuffer(GLES2DecoderImpl* decoder);
+ explicit BackRenderbuffer(
+ RenderbufferManager* renderbuffer_manager,
+ MemoryTracker* memory_tracker,
+ ContextState* state);
~BackRenderbuffer();
// Create a new render buffer.
void Create();
// Set the initial size and format of a render buffer or resize it.
- bool AllocateStorage(const gfx::Size& size, GLenum format, GLsizei samples);
+ bool AllocateStorage(const FeatureInfo* feature_info,
+ const gfx::Size& size,
+ GLenum format,
+ GLsizei samples);
// Destroy the render buffer. This must be explicitly called before destroying
// this object.
@@ -427,8 +430,9 @@ class BackRenderbuffer {
}
private:
- GLES2DecoderImpl* decoder_;
+ RenderbufferManager* renderbuffer_manager_;
MemoryTypeTracker memory_tracker_;
+ ContextState* state_;
size_t bytes_allocated_;
GLuint id_;
DISALLOW_COPY_AND_ASSIGN(BackRenderbuffer);
@@ -500,24 +504,10 @@ GLES2Decoder::GLES2Decoder()
GLES2Decoder::~GLES2Decoder() {
}
-bool GLES2Decoder::testing_force_is_angle_;
-
-void GLES2Decoder::set_testing_force_is_angle(bool force) {
- testing_force_is_angle_ = force;
-}
-
-bool GLES2Decoder::IsAngle() {
-#if defined(OS_WIN)
- return testing_force_is_angle_ ||
- gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
-#else
- return testing_force_is_angle_;
-#endif
-}
-
// This class implements GLES2Decoder so we don't have to expose all the GLES2
// cmd stuff to outside this class.
-class GLES2DecoderImpl : public GLES2Decoder {
+class GLES2DecoderImpl : public GLES2Decoder,
+ public FramebufferManager::TextureDetachObserver {
public:
// Used by PrepForSetUniformByLocation to validate types.
struct BaseUniformInfo {
@@ -554,6 +544,7 @@ class GLES2DecoderImpl : public GLES2Decoder {
virtual GLES2Util* GetGLES2Util() OVERRIDE { return &util_; }
virtual gfx::GLContext* GetGLContext() OVERRIDE { return context_.get(); }
virtual ContextGroup* GetContextGroup() OVERRIDE { return group_.get(); }
+ virtual Capabilities GetCapabilities() OVERRIDE;
virtual void RestoreState() const OVERRIDE;
virtual void RestoreActiveTexture() const OVERRIDE {
@@ -623,8 +614,6 @@ class GLES2DecoderImpl : public GLES2Decoder {
// Restores the current state to the user's settings.
void RestoreCurrentFramebufferBindings();
- void RestoreCurrentRenderbufferBindings();
- void RestoreCurrentTexture2DBindings();
// Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
void ApplyDirtyState();
@@ -639,12 +628,33 @@ class GLES2DecoderImpl : public GLES2Decoder {
virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
+ // Overridden from FramebufferManager::TextureDetachObserver:
+ virtual void OnTextureRefDetachedFromFramebuffer(
+ TextureRef* texture) OVERRIDE;
+
+ // Helpers to facilitate calling into compatible extensions.
+ static void RenderbufferStorageMultisampleHelper(
+ const FeatureInfo* feature_info,
+ GLenum target,
+ GLsizei samples,
+ GLenum internal_format,
+ GLsizei width,
+ GLsizei height);
+
+ void BlitFramebufferHelper(GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+
private:
friend class ScopedFrameBufferBinder;
- friend class ScopedGLErrorSuppressor;
friend class ScopedResolvedFrameBufferBinder;
- friend class BackTexture;
- friend class BackRenderbuffer;
friend class BackFramebuffer;
// Initialize or re-initialize the shader translator.
@@ -753,6 +763,7 @@ class GLES2DecoderImpl : public GLES2Decoder {
// Get the format of the currently bound frame buffer (either FBO or regular
// back buffer)
+ GLenum GetBoundReadFrameBufferTextureType();
GLenum GetBoundReadFrameBufferInternalFormat();
GLenum GetBoundDrawFrameBufferInternalFormat();
@@ -901,9 +912,9 @@ class GLES2DecoderImpl : public GLES2Decoder {
void LogClientServiceMapping(
const char* function_name, GLuint client_id, GLuint service_id) {
if (service_logging_) {
- DLOG(INFO) << "[" << logger_.GetLogPrefix() << "] " << function_name
- << ": client_id = " << client_id
- << ", service_id = " << service_id;
+ VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name
+ << ": client_id = " << client_id
+ << ", service_id = " << service_id;
}
}
template<typename T>
@@ -1143,8 +1154,8 @@ class GLES2DecoderImpl : public GLES2Decoder {
void DoBindVertexArrayOES(GLuint array);
void EmulateVertexArrayState();
- // Wrapper for glBlitFramebufferEXT.
- void DoBlitFramebufferEXT(
+ // Wrapper for glBlitFramebufferCHROMIUM.
+ void DoBlitFramebufferCHROMIUM(
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
@@ -1286,11 +1297,23 @@ class GLES2DecoderImpl : public GLES2Decoder {
void DoRenderbufferStorage(
GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
- // Wrapper for glRenderbufferStorageMultisampleEXT.
- void DoRenderbufferStorageMultisample(
+ // Handler for glRenderbufferStorageMultisampleCHROMIUM.
+ void DoRenderbufferStorageMultisampleCHROMIUM(
+ GLenum target, GLsizei samples, GLenum internalformat,
+ GLsizei width, GLsizei height);
+
+ // Handler for glRenderbufferStorageMultisampleEXT
+ // (multisampled_render_to_texture).
+ void DoRenderbufferStorageMultisampleEXT(
GLenum target, GLsizei samples, GLenum internalformat,
GLsizei width, GLsizei height);
+ // Common validation for multisample extensions.
+ bool ValidateRenderbufferStorageMultisample(GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
// Verifies that the currently bound multisample renderbuffer is valid
// Very slow! Only done on platforms with driver bugs that return invalid
// buffers under memory pressure
@@ -1376,9 +1399,14 @@ class GLES2DecoderImpl : public GLES2Decoder {
// buffer and bind the texture implicitly.
void UpdateStreamTextureIfNeeded(Texture* texture, GLuint texture_unit_index);
- // Returns false if unrenderable textures were replaced.
+ // If an image is bound to texture, this will call Will/DidUseTexImage
+ // if needed.
+ void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget);
+ void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget);
+
+ // Returns false if textures were replaced.
bool PrepareTexturesForRender();
- void RestoreStateForNonRenderableTextures();
+ void RestoreStateForTextures();
// Returns true if GL_FIXED attribs were simulated.
bool SimulateFixedAttribs(
@@ -1421,10 +1449,10 @@ class GLES2DecoderImpl : public GLES2Decoder {
switch (target) {
case GL_FRAMEBUFFER:
case GL_DRAW_FRAMEBUFFER_EXT:
- framebuffer = state_.bound_draw_framebuffer.get();
+ framebuffer = framebuffer_state_.bound_draw_framebuffer.get();
break;
case GL_READ_FRAMEBUFFER_EXT:
- framebuffer = state_.bound_read_framebuffer.get();
+ framebuffer = framebuffer_state_.bound_read_framebuffer.get();
break;
default:
NOTREACHED();
@@ -1501,16 +1529,36 @@ class GLES2DecoderImpl : public GLES2Decoder {
bool ShouldDeferDraws() {
return !offscreen_target_frame_buffer_.get() &&
- state_.bound_draw_framebuffer.get() == NULL &&
+ framebuffer_state_.bound_draw_framebuffer.get() == NULL &&
surface_->DeferDraws();
}
bool ShouldDeferReads() {
return !offscreen_target_frame_buffer_.get() &&
- state_.bound_read_framebuffer.get() == NULL &&
+ framebuffer_state_.bound_read_framebuffer.get() == NULL &&
surface_->DeferDraws();
}
+ error::Error WillAccessBoundFramebufferForDraw() {
+ if (ShouldDeferDraws())
+ return error::kDeferCommandUntilLater;
+ if (!offscreen_target_frame_buffer_.get() &&
+ !framebuffer_state_.bound_draw_framebuffer.get() &&
+ !surface_->SetBackbufferAllocation(true))
+ return error::kLostContext;
+ return error::kNoError;
+ }
+
+ error::Error WillAccessBoundFramebufferForRead() {
+ if (ShouldDeferReads())
+ return error::kDeferCommandUntilLater;
+ if (!offscreen_target_frame_buffer_.get() &&
+ !framebuffer_state_.bound_read_framebuffer.get() &&
+ !surface_->SetBackbufferAllocation(true))
+ return error::kLostContext;
+ return error::kNoError;
+ }
+
void ProcessPendingReadPixels();
void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
@@ -1684,22 +1732,34 @@ class GLES2DecoderImpl : public GLES2Decoder {
};
ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(
- const char* function_name, GLES2DecoderImpl* decoder)
+ const char* function_name, ErrorState* error_state)
: function_name_(function_name),
- decoder_(decoder) {
- ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(decoder_->GetErrorState(),
- function_name_);
+ error_state_(error_state) {
+ ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
}
ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
- ERRORSTATE_CLEAR_REAL_GL_ERRORS(decoder_->GetErrorState(), function_name_);
+ ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
+}
+
+static void RestoreCurrentTexture2DBindings(ContextState* state) {
+ TextureUnit& info = state->texture_units[0];
+ GLuint last_id;
+ if (info.bound_texture_2d.get()) {
+ last_id = info.bound_texture_2d->service_id();
+ } else {
+ last_id = 0;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, last_id);
+ glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
}
-ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
+ScopedTexture2DBinder::ScopedTexture2DBinder(ContextState* state,
GLuint id)
- : decoder_(decoder) {
+ : state_(state) {
ScopedGLErrorSuppressor suppressor(
- "ScopedTexture2DBinder::ctor", decoder_);
+ "ScopedTexture2DBinder::ctor", state_->GetErrorState());
// TODO(apatrick): Check if there are any other states that need to be reset
// before binding a new texture.
@@ -1709,51 +1769,52 @@ ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder,
ScopedTexture2DBinder::~ScopedTexture2DBinder() {
ScopedGLErrorSuppressor suppressor(
- "ScopedTexture2DBinder::dtor", decoder_);
- decoder_->RestoreCurrentTexture2DBindings();
+ "ScopedTexture2DBinder::dtor", state_->GetErrorState());
+ RestoreCurrentTexture2DBindings(state_);
}
-ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
+ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
GLuint id)
- : decoder_(decoder) {
+ : state_(state) {
ScopedGLErrorSuppressor suppressor(
- "ScopedRenderBufferBinder::ctor", decoder_);
+ "ScopedRenderBufferBinder::ctor", state_->GetErrorState());
glBindRenderbufferEXT(GL_RENDERBUFFER, id);
}
ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
ScopedGLErrorSuppressor suppressor(
- "ScopedRenderBufferBinder::dtor", decoder_);
- decoder_->RestoreCurrentRenderbufferBindings();
+ "ScopedRenderBufferBinder::dtor", state_->GetErrorState());
+ state_->RestoreRenderbufferBindings();
}
ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
GLuint id)
: decoder_(decoder) {
ScopedGLErrorSuppressor suppressor(
- "ScopedFrameBufferBinder::ctor", decoder_);
+ "ScopedFrameBufferBinder::ctor", decoder_->GetErrorState());
glBindFramebufferEXT(GL_FRAMEBUFFER, id);
decoder->OnFboChanged();
}
ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
ScopedGLErrorSuppressor suppressor(
- "ScopedFrameBufferBinder::dtor", decoder_);
+ "ScopedFrameBufferBinder::dtor", decoder_->GetErrorState());
decoder_->RestoreCurrentFramebufferBindings();
}
ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal)
: decoder_(decoder) {
- resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() &&
- decoder_->IsOffscreenBufferMultisampled() &&
- (!decoder_->state_.bound_read_framebuffer.get() ||
- enforce_internal_framebuffer));
+ resolve_and_bind_ = (
+ decoder_->offscreen_target_frame_buffer_.get() &&
+ decoder_->IsOffscreenBufferMultisampled() &&
+ (!decoder_->framebuffer_state_.bound_read_framebuffer.get() ||
+ enforce_internal_framebuffer));
if (!resolve_and_bind_)
return;
ScopedGLErrorSuppressor suppressor(
- "ScopedResolvedFrameBufferBinder::ctor", decoder_);
+ "ScopedResolvedFrameBufferBinder::ctor", decoder_->GetErrorState());
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
decoder_->offscreen_target_frame_buffer_->id());
GLuint targetid;
@@ -1763,7 +1824,7 @@ ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
new BackFramebuffer(decoder_));
decoder_->offscreen_resolved_frame_buffer_->Create();
decoder_->offscreen_resolved_color_texture_.reset(
- new BackTexture(decoder_));
+ new BackTexture(decoder->memory_tracker(), &decoder->state_));
decoder_->offscreen_resolved_color_texture_->Create();
DCHECK(decoder_->offscreen_saved_color_format_);
@@ -1787,13 +1848,16 @@ ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder(
const int width = decoder_->offscreen_size_.width();
const int height = decoder_->offscreen_size_.height();
glDisable(GL_SCISSOR_TEST);
- if (GLES2Decoder::IsAngle()) {
- glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height,
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
- } else {
- glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
- }
+ decoder->BlitFramebufferHelper(0,
+ 0,
+ width,
+ height,
+ 0,
+ 0,
+ width,
+ height,
+ GL_COLOR_BUFFER_BIT,
+ GL_NEAREST);
glBindFramebufferEXT(GL_FRAMEBUFFER, targetid);
}
@@ -1802,16 +1866,18 @@ ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() {
return;
ScopedGLErrorSuppressor suppressor(
- "ScopedResolvedFrameBufferBinder::dtor", decoder_);
+ "ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
decoder_->RestoreCurrentFramebufferBindings();
if (decoder_->state_.enable_flags.scissor_test) {
glEnable(GL_SCISSOR_TEST);
}
}
-BackTexture::BackTexture(GLES2DecoderImpl* decoder)
- : decoder_(decoder),
- memory_tracker_(decoder->memory_tracker(), MemoryTracker::kUnmanaged),
+BackTexture::BackTexture(
+ MemoryTracker* memory_tracker,
+ ContextState* state)
+ : memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
+ state_(state),
bytes_allocated_(0),
id_(0) {
}
@@ -1824,10 +1890,11 @@ BackTexture::~BackTexture() {
}
void BackTexture::Create() {
- ScopedGLErrorSuppressor suppressor("BackTexture::Create", decoder_);
+ ScopedGLErrorSuppressor suppressor("BackTexture::Create",
+ state_->GetErrorState());
Destroy();
glGenTextures(1, &id_);
- ScopedTexture2DBinder binder(decoder_, id_);
+ ScopedTexture2DBinder binder(state_, id_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -1849,8 +1916,9 @@ void BackTexture::Create() {
bool BackTexture::AllocateStorage(
const gfx::Size& size, GLenum format, bool zero) {
DCHECK_NE(id_, 0u);
- ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage", decoder_);
- ScopedTexture2DBinder binder(decoder_, id_);
+ ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
+ state_->GetErrorState());
+ ScopedTexture2DBinder binder(state_, id_);
uint32 image_size = 0;
GLES2Util::ComputeImageDataSizes(
size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
@@ -1889,8 +1957,9 @@ bool BackTexture::AllocateStorage(
void BackTexture::Copy(const gfx::Size& size, GLenum format) {
DCHECK_NE(id_, 0u);
- ScopedGLErrorSuppressor suppressor("BackTexture::Copy", decoder_);
- ScopedTexture2DBinder binder(decoder_, id_);
+ ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
+ state_->GetErrorState());
+ ScopedTexture2DBinder binder(state_, id_);
glCopyTexImage2D(GL_TEXTURE_2D,
0, // level
format,
@@ -1902,7 +1971,8 @@ void BackTexture::Copy(const gfx::Size& size, GLenum format) {
void BackTexture::Destroy() {
if (id_ != 0) {
- ScopedGLErrorSuppressor suppressor("BackTexture::Destroy", decoder_);
+ ScopedGLErrorSuppressor suppressor("BackTexture::Destroy",
+ state_->GetErrorState());
glDeleteTextures(1, &id_);
id_ = 0;
}
@@ -1914,9 +1984,13 @@ void BackTexture::Invalidate() {
id_ = 0;
}
-BackRenderbuffer::BackRenderbuffer(GLES2DecoderImpl* decoder)
- : decoder_(decoder),
- memory_tracker_(decoder->memory_tracker(), MemoryTracker::kUnmanaged),
+BackRenderbuffer::BackRenderbuffer(
+ RenderbufferManager* renderbuffer_manager,
+ MemoryTracker* memory_tracker,
+ ContextState* state)
+ : renderbuffer_manager_(renderbuffer_manager),
+ memory_tracker_(memory_tracker, MemoryTracker::kUnmanaged),
+ state_(state),
bytes_allocated_(0),
id_(0) {
}
@@ -1929,19 +2003,22 @@ BackRenderbuffer::~BackRenderbuffer() {
}
void BackRenderbuffer::Create() {
- ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create", decoder_);
+ ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Create",
+ state_->GetErrorState());
Destroy();
glGenRenderbuffersEXT(1, &id_);
}
-bool BackRenderbuffer::AllocateStorage(const gfx::Size& size, GLenum format,
+bool BackRenderbuffer::AllocateStorage(const FeatureInfo* feature_info,
+ const gfx::Size& size,
+ GLenum format,
GLsizei samples) {
ScopedGLErrorSuppressor suppressor(
- "BackRenderbuffer::AllocateStorage", decoder_);
- ScopedRenderBufferBinder binder(decoder_, id_);
+ "BackRenderbuffer::AllocateStorage", state_->GetErrorState());
+ ScopedRenderBufferBinder binder(state_, id_);
uint32 estimated_size = 0;
- if (!decoder_->renderbuffer_manager()->ComputeEstimatedRenderbufferSize(
+ if (!renderbuffer_manager_->ComputeEstimatedRenderbufferSize(
size.width(), size.height(), samples, format, &estimated_size)) {
return false;
}
@@ -1956,24 +2033,19 @@ bool BackRenderbuffer::AllocateStorage(const gfx::Size& size, GLenum format,
size.width(),
size.height());
} else {
- if (GLES2Decoder::IsAngle()) {
- glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER,
- samples,
- format,
- size.width(),
- size.height());
- } else {
- glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
- samples,
- format,
- size.width(),
- size.height());
- }
+ GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(feature_info,
+ GL_RENDERBUFFER,
+ samples,
+ format,
+ size.width(),
+ size.height());
}
bool success = glGetError() == GL_NO_ERROR;
if (success) {
+ // Mark the previously allocated bytes as free.
memory_tracker_.TrackMemFree(bytes_allocated_);
bytes_allocated_ = estimated_size;
+ // Track the newly allocated bytes.
memory_tracker_.TrackMemAlloc(bytes_allocated_);
}
return success;
@@ -1981,7 +2053,8 @@ bool BackRenderbuffer::AllocateStorage(const gfx::Size& size, GLenum format,
void BackRenderbuffer::Destroy() {
if (id_ != 0) {
- ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy", decoder_);
+ ScopedGLErrorSuppressor suppressor("BackRenderbuffer::Destroy",
+ state_->GetErrorState());
glDeleteRenderbuffersEXT(1, &id_);
id_ = 0;
}
@@ -2006,7 +2079,8 @@ BackFramebuffer::~BackFramebuffer() {
}
void BackFramebuffer::Create() {
- ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create", decoder_);
+ ScopedGLErrorSuppressor suppressor("BackFramebuffer::Create",
+ decoder_->GetErrorState());
Destroy();
glGenFramebuffersEXT(1, &id_);
}
@@ -2014,7 +2088,7 @@ void BackFramebuffer::Create() {
void BackFramebuffer::AttachRenderTexture(BackTexture* texture) {
DCHECK_NE(id_, 0u);
ScopedGLErrorSuppressor suppressor(
- "BackFramebuffer::AttachRenderTexture", decoder_);
+ "BackFramebuffer::AttachRenderTexture", decoder_->GetErrorState());
ScopedFrameBufferBinder binder(decoder_, id_);
GLuint attach_id = texture ? texture->id() : 0;
glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
@@ -2028,7 +2102,7 @@ void BackFramebuffer::AttachRenderBuffer(GLenum target,
BackRenderbuffer* render_buffer) {
DCHECK_NE(id_, 0u);
ScopedGLErrorSuppressor suppressor(
- "BackFramebuffer::AttachRenderBuffer", decoder_);
+ "BackFramebuffer::AttachRenderBuffer", decoder_->GetErrorState());
ScopedFrameBufferBinder binder(decoder_, id_);
GLuint attach_id = render_buffer ? render_buffer->id() : 0;
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER,
@@ -2039,7 +2113,8 @@ void BackFramebuffer::AttachRenderBuffer(GLenum target,
void BackFramebuffer::Destroy() {
if (id_ != 0) {
- ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy", decoder_);
+ ScopedGLErrorSuppressor suppressor("BackFramebuffer::Destroy",
+ decoder_->GetErrorState());
glDeleteFramebuffersEXT(1, &id_);
id_ = 0;
}
@@ -2051,7 +2126,8 @@ void BackFramebuffer::Invalidate() {
GLenum BackFramebuffer::CheckStatus() {
DCHECK_NE(id_, 0u);
- ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus", decoder_);
+ ScopedGLErrorSuppressor suppressor("BackFramebuffer::CheckStatus",
+ decoder_->GetErrorState());
ScopedFrameBufferBinder binder(decoder_, id_);
return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
}
@@ -2100,6 +2176,9 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
switches::kEnableGPUServiceLoggingGPU)),
viewport_max_width_(0),
viewport_max_height_(0),
+ texture_state_(group_->feature_info()
+ ->workarounds()
+ .texsubimage2d_faster_than_teximage2d),
validation_texture_(0),
validation_fbo_multisample_(0),
validation_fbo_(0) {
@@ -2120,11 +2199,6 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
switches::kDisableGLSLTranslator)) {
use_shader_translator_ = false;
}
-
- // TODO(gman): Consider setting this based on GPU and/or driver.
- if (IsAngle()) {
- texture_state_.teximage2d_faster_than_texsubimage2d = false;
- }
}
GLES2DecoderImpl::~GLES2DecoderImpl() {
@@ -2164,6 +2238,19 @@ bool GLES2DecoderImpl::Initialize(
context_ = context;
surface_ = surface;
+ ContextCreationAttribHelper attrib_parser;
+ if (!attrib_parser.Parse(attribs))
+ return false;
+
+ // If the failIfMajorPerformanceCaveat context creation attribute was true
+ // and we are using a software renderer, fail.
+ if (attrib_parser.fail_if_major_perf_caveat_ &&
+ feature_info_->feature_flags().is_swiftshader) {
+ group_ = NULL; // Must not destroy ContextGroup if it is not initialized.
+ Destroy(true);
+ return false;
+ }
+
if (!group_->Initialize(this, disallowed_features)) {
LOG(ERROR) << "GpuScheduler::InitializeCommon failed because group "
<< "failed to initialize.";
@@ -2226,10 +2313,6 @@ bool GLES2DecoderImpl::Initialize(
glActiveTexture(GL_TEXTURE0);
CHECK_GL_ERROR();
- ContextCreationAttribHelper attrib_parser;
- if (!attrib_parser.Parse(attribs))
- return false;
-
if (offscreen) {
if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
features().chromium_framebuffer_multisample) {
@@ -2263,7 +2346,7 @@ bool GLES2DecoderImpl::Initialize(
// ANGLE only supports packed depth/stencil formats, so use it if it is
// available.
const bool depth24_stencil8_supported =
- context_->HasExtension("GL_OES_packed_depth_stencil");
+ feature_info_->feature_flags().packed_depth24_stencil8;
VLOG(1) << "GL_OES_packed_depth_stencil "
<< (depth24_stencil8_supported ? "" : "not ") << "supported.";
if ((attrib_parser.depth_size_ > 0 || attrib_parser.stencil_size_ > 0) &&
@@ -2286,7 +2369,7 @@ bool GLES2DecoderImpl::Initialize(
// it's available, as some desktop GL drivers don't support any non-packed
// formats for depth attachments.
const bool depth24_stencil8_supported =
- context_->HasExtension("GL_EXT_packed_depth_stencil");
+ feature_info_->feature_flags().packed_depth24_stencil8;
VLOG(1) << "GL_EXT_packed_depth_stencil "
<< (depth24_stencil8_supported ? "" : "not ") << "supported.";
@@ -2314,15 +2397,19 @@ bool GLES2DecoderImpl::Initialize(
// attached to the offscreen frame buffer. The render buffer has more
// limited formats available to it, but the texture can't do multisampling.
if (IsOffscreenBufferMultisampled()) {
- offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(this));
+ offscreen_target_color_render_buffer_.reset(new BackRenderbuffer(
+ renderbuffer_manager(), memory_tracker(), &state_));
offscreen_target_color_render_buffer_->Create();
} else {
- offscreen_target_color_texture_.reset(new BackTexture(this));
+ offscreen_target_color_texture_.reset(new BackTexture(
+ memory_tracker(), &state_));
offscreen_target_color_texture_->Create();
}
- offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(this));
+ offscreen_target_depth_render_buffer_.reset(new BackRenderbuffer(
+ renderbuffer_manager(), memory_tracker(), &state_));
offscreen_target_depth_render_buffer_->Create();
- offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(this));
+ offscreen_target_stencil_render_buffer_.reset(new BackRenderbuffer(
+ renderbuffer_manager(), memory_tracker(), &state_));
offscreen_target_stencil_render_buffer_->Create();
// Create the saved offscreen texture. The target frame buffer is copied
@@ -2330,7 +2417,8 @@ bool GLES2DecoderImpl::Initialize(
offscreen_saved_frame_buffer_.reset(new BackFramebuffer(this));
offscreen_saved_frame_buffer_->Create();
//
- offscreen_saved_color_texture_.reset(new BackTexture(this));
+ offscreen_saved_color_texture_.reset(new BackTexture(
+ memory_tracker(), &state_));
offscreen_saved_color_texture_->Create();
// Allocate the render buffers at their initial size and check the status
@@ -2442,6 +2530,10 @@ bool GLES2DecoderImpl::Initialize(
context_->SetUnbindFboOnMakeCurrent();
}
+ if (feature_info_->workarounds().release_image_after_use) {
+ image_manager()->SetReleaseAfterUse();
+ }
+
// Only compositor contexts are known to use only the subset of GL
// that can be safely migrated between the iGPU and the dGPU. Mark
// those contexts as safe to forcibly transition between the GPUs.
@@ -2453,9 +2545,46 @@ bool GLES2DecoderImpl::Initialize(
AsyncPixelTransferManager::Create(context.get()));
async_pixel_transfer_manager_->Initialize(texture_manager());
+ framebuffer_manager()->AddObserver(this);
+
return true;
}
+Capabilities GLES2DecoderImpl::GetCapabilities() {
+ DCHECK(initialized());
+
+ Capabilities caps;
+
+ caps.fast_npot_mo8_textures =
+ feature_info_->workarounds().enable_chromium_fast_npot_mo8_textures;
+ caps.egl_image_external =
+ feature_info_->feature_flags().oes_egl_image_external;
+ caps.texture_format_bgra8888 =
+ feature_info_->feature_flags().ext_texture_format_bgra8888;
+ caps.texture_format_etc1 =
+ feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture;
+ caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle;
+ caps.texture_usage = feature_info_->feature_flags().angle_texture_usage;
+ caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
+ caps.discard_framebuffer =
+ feature_info_->feature_flags().ext_discard_framebuffer;
+
+#if defined(OS_MACOSX)
+ // This is unconditionally true on mac, no need to test for it at runtime.
+ caps.iosurface = true;
+#endif
+
+ // TODO(boliu): Expose this directly from GLSurface.
+ std::vector<std::string> extension_list;
+ base::SplitString(surface_->GetExtensions(), ' ', &extension_list);
+ std::set<std::string> extension_set(extension_list.begin(),
+ extension_list.end());
+ caps.post_sub_buffer =
+ extension_set.count("GL_CHROMIUM_post_sub_buffer") > 0;
+
+ return caps;
+}
+
void GLES2DecoderImpl::UpdateCapabilities() {
util_.set_num_compressed_texture_formats(
validators_->compressed_texture_format.GetValues().size());
@@ -2531,6 +2660,8 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() {
driver_bug_workarounds |= SH_EMULATE_BUILT_IN_FUNCTIONS;
if (workarounds().init_gl_position_in_vertex_shader)
driver_bug_workarounds |= SH_INIT_GL_POSITION;
+ if (workarounds().unfold_short_circuit_as_ternary_operation)
+ driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
vertex_translator_ = cache->GetTranslator(
@@ -2636,15 +2767,15 @@ void GLES2DecoderImpl::DeleteFramebuffersHelper(
Framebuffer* framebuffer =
GetFramebuffer(client_ids[ii]);
if (framebuffer && !framebuffer->IsDeleted()) {
- if (framebuffer == state_.bound_draw_framebuffer.get()) {
- state_.bound_draw_framebuffer = NULL;
+ if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
+ framebuffer_state_.bound_draw_framebuffer = NULL;
framebuffer_state_.clear_state_dirty = true;
GLenum target = supports_separate_framebuffer_binds ?
GL_DRAW_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
glBindFramebufferEXT(target, GetBackbufferServiceId());
}
- if (framebuffer == state_.bound_read_framebuffer.get()) {
- state_.bound_read_framebuffer = NULL;
+ if (framebuffer == framebuffer_state_.bound_read_framebuffer.get()) {
+ framebuffer_state_.bound_read_framebuffer = NULL;
GLenum target = supports_separate_framebuffer_binds ?
GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
glBindFramebufferEXT(target, GetBackbufferServiceId());
@@ -2668,17 +2799,17 @@ void GLES2DecoderImpl::DeleteRenderbuffersHelper(
}
// Unbind from current framebuffers.
if (supports_separate_framebuffer_binds) {
- if (state_.bound_read_framebuffer.get()) {
- state_.bound_read_framebuffer
+ if (framebuffer_state_.bound_read_framebuffer.get()) {
+ framebuffer_state_.bound_read_framebuffer
->UnbindRenderbuffer(GL_READ_FRAMEBUFFER_EXT, renderbuffer);
}
- if (state_.bound_draw_framebuffer.get()) {
- state_.bound_draw_framebuffer
+ if (framebuffer_state_.bound_draw_framebuffer.get()) {
+ framebuffer_state_.bound_draw_framebuffer
->UnbindRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, renderbuffer);
}
} else {
- if (state_.bound_draw_framebuffer.get()) {
- state_.bound_draw_framebuffer
+ if (framebuffer_state_.bound_draw_framebuffer.get()) {
+ framebuffer_state_.bound_draw_framebuffer
->UnbindRenderbuffer(GL_FRAMEBUFFER, renderbuffer);
}
}
@@ -2705,17 +2836,17 @@ void GLES2DecoderImpl::DeleteTexturesHelper(
}
// Unbind from current framebuffers.
if (supports_separate_framebuffer_binds) {
- if (state_.bound_read_framebuffer.get()) {
- state_.bound_read_framebuffer
+ if (framebuffer_state_.bound_read_framebuffer.get()) {
+ framebuffer_state_.bound_read_framebuffer
->UnbindTexture(GL_READ_FRAMEBUFFER_EXT, texture_ref);
}
- if (state_.bound_draw_framebuffer.get()) {
- state_.bound_draw_framebuffer
+ if (framebuffer_state_.bound_draw_framebuffer.get()) {
+ framebuffer_state_.bound_draw_framebuffer
->UnbindTexture(GL_DRAW_FRAMEBUFFER_EXT, texture_ref);
}
} else {
- if (state_.bound_draw_framebuffer.get()) {
- state_.bound_draw_framebuffer
+ if (framebuffer_state_.bound_draw_framebuffer.get()) {
+ framebuffer_state_.bound_draw_framebuffer
->UnbindTexture(GL_FRAMEBUFFER, texture_ref);
}
}
@@ -2733,10 +2864,10 @@ void GLES2DecoderImpl::DeleteTexturesHelper(
// } // anonymous namespace
bool GLES2DecoderImpl::MakeCurrent() {
- if (!context_.get() || !context_->MakeCurrent(surface_.get()))
+ if (!context_.get())
return false;
- if (WasContextLost()) {
+ if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) {
LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent.";
// Some D3D drivers cannot recover from device lost in the GPU process
@@ -2782,13 +2913,6 @@ void GLES2DecoderImpl::ReleaseCurrent() {
context_->ReleaseCurrent(surface_.get());
}
-void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
- Renderbuffer* renderbuffer =
- GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
- glBindRenderbufferEXT(
- GL_RENDERBUFFER, renderbuffer ? renderbuffer->service_id() : 0);
-}
-
static void RebindCurrentFramebuffer(
GLenum target,
Framebuffer* framebuffer,
@@ -2808,34 +2932,21 @@ void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
if (!features().chromium_framebuffer_multisample) {
RebindCurrentFramebuffer(
GL_FRAMEBUFFER,
- state_.bound_draw_framebuffer.get(),
+ framebuffer_state_.bound_draw_framebuffer.get(),
GetBackbufferServiceId());
} else {
RebindCurrentFramebuffer(
GL_READ_FRAMEBUFFER_EXT,
- state_.bound_read_framebuffer.get(),
+ framebuffer_state_.bound_read_framebuffer.get(),
GetBackbufferServiceId());
RebindCurrentFramebuffer(
GL_DRAW_FRAMEBUFFER_EXT,
- state_.bound_draw_framebuffer.get(),
+ framebuffer_state_.bound_draw_framebuffer.get(),
GetBackbufferServiceId());
}
OnFboChanged();
}
-void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
- TextureUnit& info = state_.texture_units[0];
- GLuint last_id;
- if (info.bound_texture_2d.get()) {
- last_id = info.bound_texture_2d->service_id();
- } else {
- last_id = 0;
- }
-
- glBindTexture(GL_TEXTURE_2D, last_id);
- glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
-}
-
bool GLES2DecoderImpl::CheckFramebufferValid(
Framebuffer* framebuffer,
GLenum target, const char* func_name) {
@@ -2902,17 +3013,18 @@ bool GLES2DecoderImpl::CheckFramebufferValid(
bool GLES2DecoderImpl::CheckBoundFramebuffersValid(const char* func_name) {
if (!features().chromium_framebuffer_multisample) {
bool valid = CheckFramebufferValid(
- state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT, func_name);
+ framebuffer_state_.bound_draw_framebuffer.get(), GL_FRAMEBUFFER_EXT,
+ func_name);
if (valid)
OnUseFramebuffer();
return valid;
}
- return CheckFramebufferValid(state_.bound_draw_framebuffer.get(),
+ return CheckFramebufferValid(framebuffer_state_.bound_draw_framebuffer.get(),
GL_DRAW_FRAMEBUFFER_EXT,
func_name) &&
- CheckFramebufferValid(state_.bound_read_framebuffer.get(),
+ CheckFramebufferValid(framebuffer_state_.bound_read_framebuffer.get(),
GL_READ_FRAMEBUFFER_EXT,
func_name);
}
@@ -2934,6 +3046,16 @@ gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
}
}
+GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() {
+ Framebuffer* framebuffer =
+ GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
+ if (framebuffer != NULL) {
+ return framebuffer->GetColorAttachmentTextureType();
+ } else {
+ return GL_UNSIGNED_BYTE;
+ }
+}
+
GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
Framebuffer* framebuffer =
GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT);
@@ -3081,8 +3203,8 @@ void GLES2DecoderImpl::Destroy(bool have_context) {
state_.texture_units.clear();
state_.bound_array_buffer = NULL;
state_.current_query = NULL;
- state_.bound_read_framebuffer = NULL;
- state_.bound_draw_framebuffer = NULL;
+ framebuffer_state_.bound_read_framebuffer = NULL;
+ framebuffer_state_.bound_draw_framebuffer = NULL;
state_.bound_renderbuffer = NULL;
if (offscreen_saved_color_texture_info_.get()) {
@@ -3189,6 +3311,7 @@ void GLES2DecoderImpl::Destroy(bool have_context) {
async_pixel_transfer_manager_.reset();
if (group_.get()) {
+ framebuffer_manager()->RemoveObserver(this);
group_->Destroy(this, have_context);
group_ = NULL;
}
@@ -3285,7 +3408,7 @@ bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
DCHECK(offscreen_target_color_format_);
if (IsOffscreenBufferMultisampled()) {
if (!offscreen_target_color_render_buffer_->AllocateStorage(
- offscreen_size_, offscreen_target_color_format_,
+ feature_info_, offscreen_size_, offscreen_target_color_format_,
offscreen_target_samples_)) {
LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
<< "to allocate storage for offscreen target color buffer.";
@@ -3301,7 +3424,7 @@ bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
}
if (offscreen_target_depth_format_ &&
!offscreen_target_depth_render_buffer_->AllocateStorage(
- offscreen_size_, offscreen_target_depth_format_,
+ feature_info_, offscreen_size_, offscreen_target_depth_format_,
offscreen_target_samples_)) {
LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
<< "to allocate storage for offscreen target depth buffer.";
@@ -3309,7 +3432,7 @@ bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
}
if (offscreen_target_stencil_format_ &&
!offscreen_target_stencil_render_buffer_->AllocateStorage(
- offscreen_size_, offscreen_target_stencil_format_,
+ feature_info_, offscreen_size_, offscreen_target_stencil_format_,
offscreen_target_samples_)) {
LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed "
<< "to allocate storage for offscreen target stencil buffer.";
@@ -3434,7 +3557,7 @@ error::Error GLES2DecoderImpl::DoCommand(
error::Error result = error::kNoError;
if (log_commands()) {
// TODO(notme): Change this to a LOG/VLOG that works in release. Tried
- // LOG(INFO), tried VLOG(1), no luck.
+ // VLOG(1), no luck.
LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" << "cmd: "
<< GetCommandName(command);
}
@@ -3648,15 +3771,16 @@ void GLES2DecoderImpl::RestoreState() const {
}
void GLES2DecoderImpl::RestoreFramebufferBindings() const {
- GLuint service_id = state_.bound_draw_framebuffer.get()
- ? state_.bound_draw_framebuffer->service_id()
- : GetBackbufferServiceId();
+ GLuint service_id =
+ framebuffer_state_.bound_draw_framebuffer.get()
+ ? framebuffer_state_.bound_draw_framebuffer->service_id()
+ : GetBackbufferServiceId();
if (!features().chromium_framebuffer_multisample) {
glBindFramebufferEXT(GL_FRAMEBUFFER, service_id);
} else {
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, service_id);
- service_id = state_.bound_read_framebuffer.get()
- ? state_.bound_read_framebuffer->service_id()
+ service_id = framebuffer_state_.bound_read_framebuffer.get()
+ ? framebuffer_state_.bound_read_framebuffer->service_id()
: GetBackbufferServiceId();
glBindFramebufferEXT(GL_READ_FRAMEBUFFER, service_id);
}
@@ -3729,10 +3853,10 @@ void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
LogClientServiceForInfo(framebuffer, client_id, "glBindFramebuffer");
if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
- state_.bound_draw_framebuffer = framebuffer;
+ framebuffer_state_.bound_draw_framebuffer = framebuffer;
}
if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
- state_.bound_read_framebuffer = framebuffer;
+ framebuffer_state_.bound_read_framebuffer = framebuffer;
}
framebuffer_state_.clear_state_dirty = true;
@@ -3860,6 +3984,13 @@ void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
void GLES2DecoderImpl::DoDiscardFramebufferEXT(GLenum target,
GLsizei numAttachments,
const GLenum* attachments) {
+ if (!features().ext_discard_framebuffer) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glDiscardFramebufferEXT",
+ "function not available");
+ return;
+ }
+
Framebuffer* framebuffer =
GetFramebufferInfoForTarget(GL_FRAMEBUFFER);
@@ -3993,13 +4124,16 @@ bool GLES2DecoderImpl::GetHelper(
case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
*num_written = 1;
if (params) {
- *params = GL_RGBA; // We don't support other formats.
+ *params = GLES2Util::GetPreferredGLReadPixelsFormat(
+ GetBoundReadFrameBufferInternalFormat());
}
return true;
case GL_IMPLEMENTATION_COLOR_READ_TYPE:
*num_written = 1;
if (params) {
- *params = GL_UNSIGNED_BYTE; // We don't support other types.
+ *params = GLES2Util::GetPreferredGLReadPixelsType(
+ GetBoundReadFrameBufferInternalFormat(),
+ GetBoundReadFrameBufferTextureType());
}
return true;
case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
@@ -4426,21 +4560,6 @@ error::Error GLES2DecoderImpl::HandleBindAttribLocation(
return error::kNoError;
}
-error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
- uint32 immediate_data_size, const cmds::BindAttribLocationImmediate& c) {
- GLuint program = static_cast<GLuint>(c.program);
- GLuint index = static_cast<GLuint>(c.index);
- uint32 name_size = c.data_size;
- const char* name = GetImmediateDataAs<const char*>(
- c, name_size, immediate_data_size);
- if (name == NULL) {
- return error::kOutOfBounds;
- }
- String name_str(name, name_size);
- DoBindAttribLocation(program, index, name_str.c_str());
- return error::kNoError;
-}
-
error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
uint32 immediate_data_size, const cmds::BindAttribLocationBucket& c) {
GLuint program = static_cast<GLuint>(c.program);
@@ -4506,22 +4625,6 @@ error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUM(
return error::kNoError;
}
-error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMImmediate(
- uint32 immediate_data_size,
- const cmds::BindUniformLocationCHROMIUMImmediate& c) {
- GLuint program = static_cast<GLuint>(c.program);
- GLint location = static_cast<GLint>(c.location);
- uint32 name_size = c.data_size;
- const char* name = GetImmediateDataAs<const char*>(
- c, name_size, immediate_data_size);
- if (name == NULL) {
- return error::kOutOfBounds;
- }
- String name_str(name, name_size);
- DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
- return error::kNoError;
-}
-
error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket(
uint32 immediate_data_size,
const cmds::BindUniformLocationCHROMIUMBucket& c) {
@@ -4714,7 +4817,7 @@ void GLES2DecoderImpl::DoFramebufferRenderbuffer(
if (error == GL_NO_ERROR) {
framebuffer->AttachRenderbuffer(attachment, renderbuffer);
}
- if (framebuffer == state_.bound_draw_framebuffer.get()) {
+ if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
framebuffer_state_.clear_state_dirty = true;
}
OnFboChanged();
@@ -4881,6 +4984,9 @@ void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
return;
}
+ if (texture_ref)
+ DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget);
+
LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name);
if (0 == samples) {
glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
@@ -4898,9 +5004,13 @@ void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
framebuffer->AttachTexture(attachment, texture_ref, textarget, level,
samples);
}
- if (framebuffer == state_.bound_draw_framebuffer.get()) {
+ if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
framebuffer_state_.clear_state_dirty = true;
}
+
+ if (texture_ref)
+ DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
+
OnFboChanged();
}
@@ -4960,7 +5070,7 @@ void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
}
}
-void GLES2DecoderImpl::DoBlitFramebufferEXT(
+void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter) {
@@ -4968,49 +5078,75 @@ void GLES2DecoderImpl::DoBlitFramebufferEXT(
if (!features().chromium_framebuffer_multisample) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
- "glBlitFramebufferEXT", "function not available");
+ "glBlitFramebufferCHROMIUM", "function not available");
+ return;
}
- if (!CheckBoundFramebuffersValid("glBlitFramebufferEXT")) {
+ if (!CheckBoundFramebuffersValid("glBlitFramebufferCHROMIUM")) {
return;
}
glDisable(GL_SCISSOR_TEST);
- if (IsAngle()) {
+ BlitFramebufferHelper(
+ srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
+}
+
+void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
+ const FeatureInfo* feature_info,
+ GLenum target,
+ GLsizei samples,
+ GLenum internal_format,
+ GLsizei width,
+ GLsizei height) {
+ // TODO(sievers): This could be resolved at the GL binding level, but the
+ // binding process is currently a bit too 'brute force'.
+ if (feature_info->feature_flags().is_angle) {
+ glRenderbufferStorageMultisampleANGLE(
+ target, samples, internal_format, width, height);
+ } else if (feature_info->feature_flags().use_core_framebuffer_multisample) {
+ glRenderbufferStorageMultisample(
+ target, samples, internal_format, width, height);
+ } else {
+ glRenderbufferStorageMultisampleEXT(
+ target, samples, internal_format, width, height);
+ }
+}
+
+void GLES2DecoderImpl::BlitFramebufferHelper(GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter) {
+ // TODO(sievers): This could be resolved at the GL binding level, but the
+ // binding process is currently a bit too 'brute force'.
+ if (feature_info_->feature_flags().is_angle) {
glBlitFramebufferANGLE(
srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ } else if (feature_info_->feature_flags().use_core_framebuffer_multisample) {
+ glBlitFramebuffer(
+ srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
} else {
glBlitFramebufferEXT(
srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
- EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
}
-void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
- GLenum target, GLsizei samples, GLenum internalformat,
- GLsizei width, GLsizei height) {
- if (!features().chromium_framebuffer_multisample &&
- !features().multisampled_render_to_texture) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glRenderbufferStorageMultisample", "function not available");
- return;
- }
-
- Renderbuffer* renderbuffer =
- GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
- if (!renderbuffer) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glRenderbufferStorageMultisample", "no renderbuffer bound");
- return;
- }
-
+bool GLES2DecoderImpl::ValidateRenderbufferStorageMultisample(
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height) {
if (samples > renderbuffer_manager()->max_samples()) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE,
"glRenderbufferStorageMultisample", "samples too large");
- return;
+ return false;
}
if (width > renderbuffer_manager()->max_renderbuffer_size() ||
@@ -5018,7 +5154,7 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE,
"glRenderbufferStorageMultisample", "dimensions too large");
- return;
+ return false;
}
uint32 estimated_size = 0;
@@ -5027,31 +5163,51 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
LOCAL_SET_GL_ERROR(
GL_OUT_OF_MEMORY,
"glRenderbufferStorageMultsample", "dimensions too large");
- return;
+ return false;
}
if (!EnsureGPUMemoryAvailable(estimated_size)) {
LOCAL_SET_GL_ERROR(
GL_OUT_OF_MEMORY,
"glRenderbufferStorageMultsample", "out of memory");
+ return false;
+ }
+
+ return true;
+}
+
+void GLES2DecoderImpl::DoRenderbufferStorageMultisampleCHROMIUM(
+ GLenum target, GLsizei samples, GLenum internalformat,
+ GLsizei width, GLsizei height) {
+ if (!features().chromium_framebuffer_multisample) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glRenderbufferStorageMultisampleCHROMIUM",
+ "function not available");
+ return;
+ }
+
+ Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
+ if (!renderbuffer) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glRenderbufferStorageMultisampleCHROMIUM",
+ "no renderbuffer bound");
+ return;
+ }
+
+ if (!ValidateRenderbufferStorageMultisample(
+ samples, internalformat, width, height)) {
return;
}
GLenum impl_format =
renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
internalformat);
- LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisample");
- if (IsAngle()) {
- glRenderbufferStorageMultisampleANGLE(
- target, samples, impl_format, width, height);
- } else if (features().use_img_for_multisampled_render_to_texture) {
- glRenderbufferStorageMultisampleIMG(
- target, samples, impl_format, width, height);
- } else {
- glRenderbufferStorageMultisampleEXT(
- target, samples, impl_format, width, height);
- }
- GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisample");
+ LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(
+ "glRenderbufferStorageMultisampleCHROMIUM");
+ RenderbufferStorageMultisampleHelper(
+ feature_info_, target, samples, impl_format, width, height);
+ GLenum error =
+ LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleCHROMIUM");
if (error == GL_NO_ERROR) {
if (workarounds().validate_multisample_buffer_allocation) {
@@ -5059,7 +5215,7 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
renderbuffer->service_id(), impl_format)) {
LOCAL_SET_GL_ERROR(
GL_OUT_OF_MEMORY,
- "glRenderbufferStorageMultisample", "out of memory");
+ "glRenderbufferStorageMultisampleCHROMIUM", "out of memory");
return;
}
}
@@ -5072,6 +5228,51 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
}
}
+// This is the handler for multisampled_render_to_texture extensions.
+void GLES2DecoderImpl::DoRenderbufferStorageMultisampleEXT(
+ GLenum target, GLsizei samples, GLenum internalformat,
+ GLsizei width, GLsizei height) {
+ if (!features().multisampled_render_to_texture) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION,
+ "glRenderbufferStorageMultisampleEXT", "function not available");
+ return;
+ }
+
+ Renderbuffer* renderbuffer = GetRenderbufferInfoForTarget(GL_RENDERBUFFER);
+ if (!renderbuffer) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glRenderbufferStorageMultisampleEXT",
+ "no renderbuffer bound");
+ return;
+ }
+
+ if (!ValidateRenderbufferStorageMultisample(
+ samples, internalformat, width, height)) {
+ return;
+ }
+
+ GLenum impl_format =
+ renderbuffer_manager()->InternalRenderbufferFormatToImplFormat(
+ internalformat);
+ LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glRenderbufferStorageMultisampleEXT");
+ if (features().use_img_for_multisampled_render_to_texture) {
+ glRenderbufferStorageMultisampleIMG(
+ target, samples, impl_format, width, height);
+ } else {
+ glRenderbufferStorageMultisampleEXT(
+ target, samples, impl_format, width, height);
+ }
+ GLenum error = LOCAL_PEEK_GL_ERROR("glRenderbufferStorageMultisampleEXT");
+ if (error == GL_NO_ERROR) {
+ // TODO(gman): If renderbuffers tracked which framebuffers they were
+ // attached to we could just mark those framebuffers as not complete.
+ framebuffer_manager()->IncFramebufferStateChangeCount();
+ renderbuffer_manager()->SetInfo(
+ renderbuffer, samples, internalformat, width, height);
+ }
+}
+
// This function validates the allocation of a multisampled renderbuffer
// by clearing it to a key color, blitting the contents to a texture, and
// reading back the color to ensure it matches the key.
@@ -5144,7 +5345,8 @@ bool GLES2DecoderImpl::VerifyMultisampleRenderbufferIntegrity(
glBindFramebufferEXT(GL_READ_FRAMEBUFFER, validation_fbo_multisample_);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, validation_fbo_);
- glBlitFramebufferEXT(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ BlitFramebufferHelper(
+ 0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// Read a pixel from the buffer.
glBindFramebufferEXT(GL_FRAMEBUFFER, validation_fbo_);
@@ -5239,13 +5441,14 @@ void GLES2DecoderImpl::DoLinkProgram(GLuint program_id) {
if (program->Link(shader_manager(),
vertex_translator,
fragment_translator,
- feature_info_.get(),
+ workarounds().count_all_in_varyings_packing ?
+ Program::kCountAll : Program::kCountOnlyStaticallyUsed,
shader_cache_callback_)) {
if (program == state_.current_program.get()) {
- if (workarounds().use_current_program_after_successful_link) {
+ if (workarounds().use_current_program_after_successful_link)
glUseProgram(program->service_id());
- }
- program_manager()->ClearUniforms(program);
+ if (workarounds().clear_uniforms_before_first_program_use)
+ program_manager()->ClearUniforms(program);
}
}
};
@@ -5711,6 +5914,8 @@ void GLES2DecoderImpl::DoUseProgram(GLuint program_id) {
glUseProgram(service_id);
if (state_.current_program.get()) {
program_manager()->UseProgram(state_.current_program.get());
+ if (workarounds().clear_uniforms_before_first_program_use)
+ program_manager()->ClearUniforms(program);
}
}
@@ -5738,11 +5943,49 @@ void GLES2DecoderImpl::UpdateStreamTextureIfNeeded(Texture* texture,
}
}
+void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
+ Texture* texture, GLenum textarget) {
+ // This might be supported in the future.
+ if (textarget != GL_TEXTURE_2D)
+ return;
+ // Image is already in use if texture is attached to a framebuffer.
+ if (texture && !texture->IsAttachedToFramebuffer()) {
+ gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
+ if (image) {
+ ScopedGLErrorSuppressor suppressor(
+ "GLES2DecoderImpl::DoWillUseTexImageIfNeeded",
+ GetErrorState());
+ glBindTexture(textarget, texture->service_id());
+ image->WillUseTexImage();
+ RestoreCurrentTexture2DBindings(&state_);
+ }
+ }
+}
+
+void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
+ Texture* texture, GLenum textarget) {
+ // This might be supported in the future.
+ if (textarget != GL_TEXTURE_2D)
+ return;
+ // Image is still in use if texture is attached to a framebuffer.
+ if (texture && !texture->IsAttachedToFramebuffer()) {
+ gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
+ if (image) {
+ ScopedGLErrorSuppressor suppressor(
+ "GLES2DecoderImpl::DoDidUseTexImageIfNeeded",
+ GetErrorState());
+ glBindTexture(textarget, texture->service_id());
+ image->DidUseTexImage();
+ RestoreCurrentTexture2DBindings(&state_);
+ }
+ }
+}
+
bool GLES2DecoderImpl::PrepareTexturesForRender() {
DCHECK(state_.current_program.get());
- bool have_unrenderable_textures =
- texture_manager()->HaveUnrenderableTextures();
- if (!have_unrenderable_textures && !features().oes_egl_image_external) {
+ if (!texture_manager()->HaveUnrenderableTextures() &&
+ !texture_manager()->HaveImages() &&
+ !features().oes_egl_image_external) {
return true;
}
@@ -5757,16 +6000,14 @@ bool GLES2DecoderImpl::PrepareTexturesForRender() {
GLuint texture_unit_index = uniform_info->texture_units[jj];
if (texture_unit_index < state_.texture_units.size()) {
TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
- TextureRef* texture =
+ TextureRef* texture_ref =
texture_unit.GetInfoForSamplerType(uniform_info->type).get();
- if (texture)
- UpdateStreamTextureIfNeeded(texture->texture(), texture_unit_index);
- if (have_unrenderable_textures &&
- (!texture || !texture_manager()->CanRender(texture))) {
+ GLenum textarget = GetBindTargetForSamplerType(uniform_info->type);
+ if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
textures_set = true;
glActiveTexture(GL_TEXTURE0 + texture_unit_index);
glBindTexture(
- GetBindTargetForSamplerType(uniform_info->type),
+ textarget,
texture_manager()->black_texture_id(uniform_info->type));
LOCAL_RENDER_WARNING(
std::string("texture bound to texture unit ") +
@@ -5774,7 +6015,23 @@ bool GLES2DecoderImpl::PrepareTexturesForRender() {
" is not renderable. It maybe non-power-of-2 and have"
" incompatible texture filtering or is not"
" 'texture complete'");
+ continue;
}
+
+ Texture* texture = texture_ref->texture();
+ if (textarget == GL_TEXTURE_2D) {
+ gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
+ if (image && !texture->IsAttachedToFramebuffer()) {
+ ScopedGLErrorSuppressor suppressor(
+ "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
+ textures_set = true;
+ glActiveTexture(GL_TEXTURE0 + texture_unit_index);
+ image->WillUseTexImage();
+ continue;
+ }
+ }
+
+ UpdateStreamTextureIfNeeded(texture, texture_unit_index);
}
// else: should this be an error?
}
@@ -5782,7 +6039,7 @@ bool GLES2DecoderImpl::PrepareTexturesForRender() {
return !textures_set;
}
-void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
+void GLES2DecoderImpl::RestoreStateForTextures() {
DCHECK(state_.current_program.get());
const Program::SamplerIndices& sampler_indices =
state_.current_program->sampler_indices();
@@ -5795,9 +6052,7 @@ void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
if (texture_unit_index < state_.texture_units.size()) {
TextureUnit& texture_unit = state_.texture_units[texture_unit_index];
TextureRef* texture_ref =
- uniform_info->type == GL_SAMPLER_2D
- ? texture_unit.bound_texture_2d.get()
- : texture_unit.bound_texture_cube_map.get();
+ texture_unit.GetInfoForSamplerType(uniform_info->type).get();
if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
glActiveTexture(GL_TEXTURE0 + texture_unit_index);
// Get the texture_ref info that was previously bound here.
@@ -5806,6 +6061,20 @@ void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() {
: texture_unit.bound_texture_cube_map.get();
glBindTexture(texture_unit.bind_target,
texture_ref ? texture_ref->service_id() : 0);
+ continue;
+ }
+
+ Texture* texture = texture_ref->texture();
+ if (texture_unit.bind_target == GL_TEXTURE_2D) {
+ gfx::GLImage* image = texture->GetLevelImage(
+ texture_unit.bind_target, 0);
+ if (image && !texture->IsAttachedToFramebuffer()) {
+ ScopedGLErrorSuppressor suppressor(
+ "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
+ glActiveTexture(GL_TEXTURE0 + texture_unit_index);
+ image->DidUseTexImage();
+ continue;
+ }
}
}
}
@@ -6095,8 +6364,9 @@ error::Error GLES2DecoderImpl::DoDrawArrays(
GLint first,
GLsizei count,
GLsizei primcount) {
- if (ShouldDeferDraws())
- return error::kDeferCommandUntilLater;
+ error::Error error = WillAccessBoundFramebufferForDraw();
+ if (error != error::kNoError)
+ return error;
if (!validators_->draw_mode.IsValid(mode)) {
LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, mode, "mode");
return error::kNoError;
@@ -6148,7 +6418,7 @@ error::Error GLES2DecoderImpl::DoDrawArrays(
}
ProcessPendingQueries();
if (textures_set) {
- RestoreStateForNonRenderableTextures();
+ RestoreStateForTextures();
}
if (simulated_fixed_attribs) {
RestoreStateForSimulatedFixedAttribs();
@@ -6195,8 +6465,9 @@ error::Error GLES2DecoderImpl::DoDrawElements(
GLenum type,
int32 offset,
GLsizei primcount) {
- if (ShouldDeferDraws())
- return error::kDeferCommandUntilLater;
+ error::Error error = WillAccessBoundFramebufferForDraw();
+ if (error != error::kNoError)
+ return error;
if (!state_.vertex_attrib_manager->element_array_buffer()) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, function_name, "No element array buffer bound");
@@ -6282,7 +6553,7 @@ error::Error GLES2DecoderImpl::DoDrawElements(
ProcessPendingQueries();
if (textures_set) {
- RestoreStateForNonRenderableTextures();
+ RestoreStateForTextures();
}
if (simulated_fixed_attribs) {
RestoreStateForSimulatedFixedAttribs();
@@ -6371,17 +6642,6 @@ error::Error GLES2DecoderImpl::HandleShaderSource(
return ShaderSourceHelper(c.shader, data, data_size);
}
-error::Error GLES2DecoderImpl::HandleShaderSourceImmediate(
- uint32 immediate_data_size, const cmds::ShaderSourceImmediate& c) {
- uint32 data_size = c.data_size;
- const char* data = GetImmediateDataAs<const char*>(
- c, data_size, immediate_data_size);
- if (!data) {
- return error::kOutOfBounds;
- }
- return ShaderSourceHelper(c.shader, data, data_size);
-}
-
error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
uint32 immediate_data_size, const cmds::ShaderSourceBucket& c) {
Bucket* bucket = GetBucket(c.data_bucket_id);
@@ -6405,7 +6665,11 @@ void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
vertex_translator_.get() : fragment_translator_.get();
}
- program_manager()->DoCompileShader(shader, translator, feature_info_.get());
+ program_manager()->DoCompileShader(
+ shader,
+ translator,
+ feature_info_->feature_flags().angle_translated_shader_source ?
+ ProgramManager::kANGLE : ProgramManager::kGL);
};
void GLES2DecoderImpl::DoGetShaderiv(
@@ -6856,6 +7120,29 @@ error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
return error::kNoError;
}
+template <typename pixel_data_type>
+static void WriteAlphaData(
+ void *pixels, uint32 row_count, uint32 channel_count,
+ uint32 alpha_channel_index, uint32 unpadded_row_size,
+ uint32 padded_row_size, pixel_data_type alpha_value) {
+ DCHECK_GT(channel_count, 0U);
+ DCHECK_EQ(unpadded_row_size % sizeof(pixel_data_type), 0U);
+ uint32 unpadded_row_size_in_elements =
+ unpadded_row_size / sizeof(pixel_data_type);
+ DCHECK_EQ(padded_row_size % sizeof(pixel_data_type), 0U);
+ uint32 padded_row_size_in_elements =
+ padded_row_size / sizeof(pixel_data_type);
+ pixel_data_type* dst =
+ static_cast<pixel_data_type*>(pixels) + alpha_channel_index;
+ for (uint32 yy = 0; yy < row_count; ++yy) {
+ pixel_data_type* end = dst + unpadded_row_size_in_elements;
+ for (pixel_data_type* d = dst; d < end; d += channel_count) {
+ *d = alpha_value;
+ }
+ dst += padded_row_size_in_elements;
+ }
+}
+
void GLES2DecoderImpl::FinishReadPixels(
const cmds::ReadPixels& c,
GLuint buffer) {
@@ -6924,38 +7211,49 @@ void GLES2DecoderImpl::FinishReadPixels(
&unpadded_row_size, &padded_row_size)) {
return;
}
- // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
- // of this implementation.
- if (type != GL_UNSIGNED_BYTE) {
- return;
- }
+
+ uint32 channel_count = 0;
+ uint32 alpha_channel = 0;
switch (format) {
case GL_RGBA:
case GL_BGRA_EXT:
- case GL_ALPHA: {
- int offset = (format == GL_ALPHA) ? 0 : 3;
- int step = (format == GL_ALPHA) ? 1 : 4;
- uint8* dst = static_cast<uint8*>(pixels) + offset;
- for (GLint yy = 0; yy < height; ++yy) {
- uint8* end = dst + unpadded_row_size;
- for (uint8* d = dst; d < end; d += step) {
- *d = 255;
- }
- dst += padded_row_size;
- }
+ channel_count = 4;
+ alpha_channel = 3;
break;
- }
- default:
+ case GL_ALPHA:
+ channel_count = 1;
+ alpha_channel = 0;
break;
}
+
+ if (channel_count > 0) {
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ WriteAlphaData<uint8>(
+ pixels, height, channel_count, alpha_channel, unpadded_row_size,
+ padded_row_size, 0xFF);
+ break;
+ case GL_FLOAT:
+ WriteAlphaData<float>(
+ pixels, height, channel_count, alpha_channel, unpadded_row_size,
+ padded_row_size, 1.0f);
+ break;
+ case GL_HALF_FLOAT:
+ WriteAlphaData<uint16>(
+ pixels, height, channel_count, alpha_channel, unpadded_row_size,
+ padded_row_size, 0x3C00);
+ break;
+ }
+ }
}
}
error::Error GLES2DecoderImpl::HandleReadPixels(
uint32 immediate_data_size, const cmds::ReadPixels& c) {
- if (ShouldDeferReads())
- return error::kDeferCommandUntilLater;
+ error::Error fbo_error = WillAccessBoundFramebufferForRead();
+ if (fbo_error != error::kNoError)
+ return fbo_error;
GLint x = c.x;
GLint y = c.y;
GLsizei width = c.width;
@@ -6992,10 +7290,26 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", format, "format");
return error::kNoError;
}
- if (!validators_->pixel_type.IsValid(type)) {
+ if (!validators_->read_pixel_type.IsValid(type)) {
LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type");
return error::kNoError;
}
+ if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB &&
+ format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) {
+ // format and type are acceptable enums but not guaranteed to be supported
+ // for this framebuffer. Have to ask gl if they are valid.
+ GLint preferred_format = 0;
+ DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format);
+ GLint preferred_type = 0;
+ DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type);
+ if (format != static_cast<GLenum>(preferred_format) ||
+ type != static_cast<GLenum>(preferred_type)) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible "
+ "with the current read framebuffer");
+ return error::kNoError;
+ }
+ }
if (width == 0 || height == 0) {
return error::kNoError;
}
@@ -7213,19 +7527,6 @@ error::Error GLES2DecoderImpl::HandleGetAttribLocation(
c.program, c.location_shm_id, c.location_shm_offset, name_str);
}
-error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate(
- uint32 immediate_data_size, const cmds::GetAttribLocationImmediate& c) {
- uint32 name_size = c.data_size;
- const char* name = GetImmediateDataAs<const char*>(
- c, name_size, immediate_data_size);
- if (!name) {
- return error::kOutOfBounds;
- }
- String name_str(name, name_size);
- return GetAttribLocationHelper(
- c.program, c.location_shm_id, c.location_shm_offset, name_str);
-}
-
error::Error GLES2DecoderImpl::HandleGetAttribLocationBucket(
uint32 immediate_data_size, const cmds::GetAttribLocationBucket& c) {
Bucket* bucket = GetBucket(c.name_bucket_id);
@@ -7285,19 +7586,6 @@ error::Error GLES2DecoderImpl::HandleGetUniformLocation(
c.program, c.location_shm_id, c.location_shm_offset, name_str);
}
-error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate(
- uint32 immediate_data_size, const cmds::GetUniformLocationImmediate& c) {
- uint32 name_size = c.data_size;
- const char* name = GetImmediateDataAs<const char*>(
- c, name_size, immediate_data_size);
- if (!name) {
- return error::kOutOfBounds;
- }
- String name_str(name, name_size);
- return GetUniformLocationHelper(
- c.program, c.location_shm_id, c.location_shm_offset, name_str);
-}
-
error::Error GLES2DecoderImpl::HandleGetUniformLocationBucket(
uint32 immediate_data_size, const cmds::GetUniformLocationBucket& c) {
Bucket* bucket = GetBucket(c.name_bucket_id);
@@ -7397,20 +7685,6 @@ error::Error GLES2DecoderImpl::HandleBufferData(
return error::kNoError;
}
-error::Error GLES2DecoderImpl::HandleBufferDataImmediate(
- uint32 immediate_data_size, const cmds::BufferDataImmediate& c) {
- GLenum target = static_cast<GLenum>(c.target);
- GLsizeiptr size = static_cast<GLsizeiptr>(c.size);
- const void* data = GetImmediateDataAs<const void*>(
- c, size, immediate_data_size);
- if (!data) {
- return error::kOutOfBounds;
- }
- GLenum usage = static_cast<GLenum>(c.usage);
- buffer_manager()->ValidateAndDoBufferData(&state_, target, size, data, usage);
- return error::kNoError;
-}
-
void GLES2DecoderImpl::DoBufferSubData(
GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
// Just delegate it. Some validation is actually done before this.
@@ -7429,7 +7703,8 @@ bool GLES2DecoderImpl::ClearLevel(
int height,
bool is_texture_immutable) {
uint32 channels = GLES2Util::GetChannelsForFormat(format);
- if (IsAngle() && (channels & GLES2Util::kDepth) != 0) {
+ if (feature_info_->feature_flags().angle_depth_texture &&
+ (channels & GLES2Util::kDepth) != 0) {
// It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D
// on depth formats.
GLuint fb = 0;
@@ -7762,24 +8037,6 @@ error::Error GLES2DecoderImpl::HandleCompressedTexImage2D(
target, level, internal_format, width, height, border, image_size, data);
}
-error::Error GLES2DecoderImpl::HandleCompressedTexImage2DImmediate(
- uint32 immediate_data_size, const cmds::CompressedTexImage2DImmediate& c) {
- GLenum target = static_cast<GLenum>(c.target);
- GLint level = static_cast<GLint>(c.level);
- 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);
- GLsizei image_size = static_cast<GLsizei>(c.imageSize);
- const void* data = GetImmediateDataAs<const void*>(
- c, image_size, immediate_data_size);
- if (!data) {
- return error::kOutOfBounds;
- }
- return DoCompressedTexImage2D(
- target, level, internal_format, width, height, border, image_size, data);
-}
-
error::Error GLES2DecoderImpl::HandleCompressedTexImage2DBucket(
uint32 immediate_data_size, const cmds::CompressedTexImage2DBucket& c) {
GLenum target = static_cast<GLenum>(c.target);
@@ -7893,38 +8150,6 @@ error::Error GLES2DecoderImpl::HandleTexImage2D(
return error::kNoError;
}
-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);
- // 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);
- GLenum format = static_cast<GLenum>(c.format);
- GLenum type = static_cast<GLenum>(c.type);
- uint32 size;
- if (!GLES2Util::ComputeImageDataSizes(
- width, height, format, type, state_.unpack_alignment, &size,
- NULL, NULL)) {
- return error::kOutOfBounds;
- }
- const void* pixels = GetImmediateDataAs<const void*>(
- c, size, immediate_data_size);
- if (!pixels) {
- return error::kOutOfBounds;
- }
-
- 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;
-}
-
void GLES2DecoderImpl::DoCompressedTexSubImage2D(
GLenum target,
GLint level,
@@ -8346,7 +8571,7 @@ error::Error GLES2DecoderImpl::DoTexSubImage2D(
return error::kNoError;
}
- if (texture_state_.teximage2d_faster_than_texsubimage2d &&
+ if (!texture_state_.texsubimage2d_faster_than_teximage2d &&
!texture->IsImmutable()) {
ScopedTextureUploadTimer timer(&texture_state_);
// NOTE: In OpenGL ES 2.0 border is always zero and format is always the
@@ -8389,32 +8614,6 @@ error::Error GLES2DecoderImpl::HandleTexSubImage2D(
target, level, xoffset, yoffset, width, height, format, type, pixels);
}
-error::Error GLES2DecoderImpl::HandleTexSubImage2DImmediate(
- uint32 immediate_data_size, const cmds::TexSubImage2DImmediate& c) {
- GLboolean internal = static_cast<GLboolean>(c.internal);
- if (internal == GL_TRUE && texture_state_.tex_image_2d_failed)
- return error::kNoError;
-
- GLenum target = static_cast<GLenum>(c.target);
- GLint level = static_cast<GLint>(c.level);
- GLint xoffset = static_cast<GLint>(c.xoffset);
- GLint yoffset = static_cast<GLint>(c.yoffset);
- GLsizei width = static_cast<GLsizei>(c.width);
- GLsizei height = static_cast<GLsizei>(c.height);
- GLenum format = static_cast<GLenum>(c.format);
- GLenum type = static_cast<GLenum>(c.type);
- uint32 data_size;
- if (!GLES2Util::ComputeImageDataSizes(
- width, height, format, type, state_.unpack_alignment, &data_size,
- NULL, NULL)) {
- return error::kOutOfBounds;
- }
- const void* pixels = GetImmediateDataAs<const void*>(
- c, data_size, immediate_data_size);
- return DoTexSubImage2D(
- target, level, xoffset, yoffset, width, height, format, type, pixels);
-}
-
error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
uint32 immediate_data_size, const cmds::GetVertexAttribPointerv& c) {
GLuint index = static_cast<GLuint>(c.index);
@@ -8809,7 +9008,7 @@ void GLES2DecoderImpl::DoSwapBuffers() {
if (offscreen_size_.width() == 0 || offscreen_size_.height() == 0)
return;
ScopedGLErrorSuppressor suppressor(
- "GLES2DecoderImpl::DoSwapBuffers", this);
+ "GLES2DecoderImpl::DoSwapBuffers", GetErrorState());
if (IsOffscreenBufferMultisampled()) {
// For multisampled buffers, resolve the frame buffer.
@@ -8837,7 +9036,7 @@ void GLES2DecoderImpl::DoSwapBuffers() {
// Ensure the side effects of the copy are visible to the parent
// context. There is no need to do this for ANGLE because it uses a
// single D3D device for all contexts.
- if (!IsAngle())
+ if (!feature_info_->feature_flags().is_angle)
glFlush();
}
} else {
@@ -9128,6 +9327,18 @@ error::Error GLES2DecoderImpl::HandleWaitSyncPointCHROMIUM(
error::kNoError : error::kDeferCommandUntilLater;
}
+error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
+ uint32 immediate_data_size, const cmds::DiscardBackbufferCHROMIUM& c) {
+ if (surface_->DeferDraws())
+ return error::kDeferCommandUntilLater;
+ if (!surface_->SetBackbufferAllocation(false))
+ return error::kLostContext;
+ backbuffer_needs_clear_bits_ |= GL_COLOR_BUFFER_BIT;
+ backbuffer_needs_clear_bits_ |= GL_DEPTH_BUFFER_BIT;
+ backbuffer_needs_clear_bits_ |= GL_STENCIL_BUFFER_BIT;
+ return error::kNoError;
+}
+
bool GLES2DecoderImpl::GenQueriesEXTHelper(
GLsizei n, const GLuint* client_ids) {
for (GLsizei ii = 0; ii < n; ++ii) {
@@ -9649,34 +9860,17 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
if (dest_texture->target() != GL_TEXTURE_2D ||
(source_texture->target() != GL_TEXTURE_2D &&
source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_VALUE,
- "glCopyTextureCHROMIUM", "invalid texture target binding");
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
+ "glCopyTextureCHROMIUM",
+ "invalid texture target binding");
return;
}
int source_width, source_height, dest_width, dest_height;
- if (source_texture->target() == GL_TEXTURE_2D) {
- if (!source_texture->GetLevelSize(GL_TEXTURE_2D, 0, &source_width,
- &source_height)) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_VALUE,
- "glCopyTextureChromium", "source texture has no level 0");
- return;
- }
-
- // Check that this type of texture is allowed.
- if (!texture_manager()->ValidForTarget(GL_TEXTURE_2D, level, source_width,
- source_height, 1)) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_VALUE,
- "glCopyTextureCHROMIUM", "Bad dimensions");
- return;
- }
- }
-
- if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
+ if (source_texture->IsStreamTexture()) {
+ DCHECK_EQ(source_texture->target(),
+ static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES));
DCHECK(stream_texture_manager());
StreamTexture* stream_tex =
stream_texture_manager()->LookupStreamTexture(
@@ -9696,6 +9890,30 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
"glCopyTextureChromium", "invalid streamtexture size");
return;
}
+ } else {
+ if (!source_texture->GetLevelSize(
+ source_texture->target(), 0, &source_width, &source_height)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
+ "glCopyTextureChromium",
+ "source texture has no level 0");
+ return;
+ }
+
+ // Check that this type of texture is allowed.
+ if (!texture_manager()->ValidForTarget(
+ source_texture->target(), level, source_width, source_height, 1)) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_VALUE, "glCopyTextureCHROMIUM", "Bad dimensions");
+ return;
+ }
+ }
+
+ // Clear the source texture if necessary.
+ if (!texture_manager()->ClearTextureLevel(
+ this, source_texture_ref, source_texture->target(), 0)) {
+ LOCAL_SET_GL_ERROR(
+ GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
+ return;
}
// Defer initializing the CopyTextureCHROMIUMResourceManager until it is
@@ -9732,7 +9950,7 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
0, internal_format, dest_type, NULL);
GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
if (error != GL_NO_ERROR) {
- RestoreCurrentTexture2DBindings();
+ RestoreCurrentTexture2DBindings(&state_);
return;
}
@@ -9744,6 +9962,8 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
dest_texture_ref, GL_TEXTURE_2D, level, true);
}
+ DoWillUseTexImageIfNeeded(source_texture, source_texture->target());
+
// GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix
// before presenting.
if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
@@ -9776,6 +9996,8 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
unpack_premultiply_alpha_,
unpack_unpremultiply_alpha_);
}
+
+ DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
}
static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
@@ -9831,7 +10053,7 @@ void GLES2DecoderImpl::DoTexStorage2DEXT(
GLsizei height) {
TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT");
if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
- TextureManager::ComputeMipMapCount(width, height, 1) < levels) {
+ TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
return;
@@ -9901,15 +10123,7 @@ void GLES2DecoderImpl::DoTexStorage2DEXT(
error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
uint32 immediate_data_size, const cmds::GenMailboxCHROMIUM& c) {
- MailboxName name;
- mailbox_manager()->GenerateMailboxName(&name);
- uint32 bucket_id = static_cast<uint32>(c.bucket_id);
- Bucket* bucket = CreateBucket(bucket_id);
-
- bucket->SetSize(GL_MAILBOX_SIZE_CHROMIUM);
- bucket->SetData(&name, 0, GL_MAILBOX_SIZE_CHROMIUM);
-
- return error::kNoError;
+ return error::kUnknownCommand;
}
void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
@@ -10034,13 +10248,6 @@ void GLES2DecoderImpl::DoPopGroupMarkerEXT(void) {
void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
GLenum target, GLint image_id) {
TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
- if (target != GL_TEXTURE_2D) {
- // This might be supported in the future.
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glBindTexImage2DCHROMIUM", "requires TEXTURE_2D target");
- return;
- }
// Default target might be conceptually valid, but disallow it to avoid
// accidents.
@@ -10063,8 +10270,8 @@ void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
{
ScopedGLErrorSuppressor suppressor(
- "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", this);
- if (!gl_image->BindTexImage()) {
+ "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM", GetErrorState());
+ if (!gl_image->BindTexImage(target)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glBindTexImage2DCHROMIUM", "fail to bind image with the given ID");
@@ -10082,13 +10289,6 @@ void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM(
void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
GLenum target, GLint image_id) {
TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM");
- if (target != GL_TEXTURE_2D) {
- // This might be supported in the future.
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glReleaseTexImage2DCHROMIUM", "requires TEXTURE_2D target");
- return;
- }
// Default target might be conceptually valid, but disallow it to avoid
// accidents.
@@ -10115,8 +10315,8 @@ void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM(
{
ScopedGLErrorSuppressor suppressor(
- "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", this);
- gl_image->ReleaseTexImage();
+ "GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM", GetErrorState());
+ gl_image->ReleaseTexImage(target);
}
texture_manager()->SetLevelInfo(
@@ -10449,6 +10649,12 @@ error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
return error::kNoError;
}
+void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
+ TextureRef* texture_ref) {
+ Texture* texture = texture_ref->texture();
+ DoDidUseTexImageIfNeeded(texture, texture->target());
+}
+
// Include the auto-generated part of this file. We split this because it means
// we can easily edit the non-auto generated parts right here in this file
// instead of having to edit some template or the code generator.