summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorreveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-19 10:22:56 +0000
committerreveman@chromium.org <reveman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-19 10:22:56 +0000
commit8a48e732c0dc67b22f0b2cdce8bf750e273a4628 (patch)
treea3f0260baa264de95d1ffb21815ebcf223dfdee2
parent10ebc9183caa8dd392ec89cc6c571332c4194741 (diff)
downloadchromium_src-8a48e732c0dc67b22f0b2cdce8bf750e273a4628.zip
chromium_src-8a48e732c0dc67b22f0b2cdce8bf750e273a4628.tar.gz
chromium_src-8a48e732c0dc67b22f0b2cdce8bf750e273a4628.tar.bz2
gpu: Add Will/DidUseTexImage to GLImage API.
WillUseTexImage/DidUseTexImage is called before/after the image is used for sampling. The result is that the client only has to call bind/releaseTexImage2D when contents have changed, which allows for more efficient GLImage implementations as work required before use can be separated from work required when contents have changed. BUG=261649 TEST=gpu_unittests --gtest_filter=SharedTextureTest.Images && gpu_unittests --gtest_filter=GLES2DecoderWithShaderTest.UseTexImage && cc_unittests --gtest_filter=ResourceProviderTests/ResourceProviderTest.Image_GLTexture* && gl_tests --gtest_filter=MockGpuMemoryBufferTest.Lifecycle Review URL: https://codereview.chromium.org/23129010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@229532 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/resources/resource_provider.cc33
-rw-r--r--cc/resources/resource_provider.h5
-rw-r--r--cc/resources/resource_provider_unittest.cc21
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.cc26
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.h28
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc117
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc140
-rw-r--r--gpu/command_buffer/service/texture_manager.cc40
-rw-r--r--gpu/command_buffer/service/texture_manager.h17
-rw-r--r--gpu/command_buffer/service/texture_manager_unittest.cc60
-rw-r--r--ui/gl/gl_image.cc8
-rw-r--r--ui/gl/gl_image.h6
-rw-r--r--ui/gl/gl_image_egl.cc55
-rw-r--r--ui/gl/gl_image_egl.h3
-rw-r--r--ui/gl/gl_image_glx.cc10
-rw-r--r--ui/gl/gl_image_glx.h2
-rw-r--r--ui/gl/gl_image_shm.cc14
-rw-r--r--ui/gl/gl_image_shm.h2
-rw-r--r--ui/gl/gl_image_stub.cc13
-rw-r--r--ui/gl/gl_image_stub.h4
20 files changed, 533 insertions, 71 deletions
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index e7d8c13..d76fc4b 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -111,6 +111,8 @@ ResourceProvider::Resource::Resource()
original_filter(0),
filter(0),
image_id(0),
+ bound_image_id(0),
+ dirty_image(false),
texture_pool(0),
wrap_mode(0),
lost(false),
@@ -150,6 +152,8 @@ ResourceProvider::Resource::Resource(unsigned texture_id,
original_filter(filter),
filter(filter),
image_id(0),
+ bound_image_id(0),
+ dirty_image(false),
texture_pool(texture_pool),
wrap_mode(wrap_mode),
lost(false),
@@ -185,6 +189,8 @@ ResourceProvider::Resource::Resource(uint8_t* pixels,
original_filter(filter),
filter(filter),
image_id(0),
+ bound_image_id(0),
+ dirty_image(false),
texture_pool(0),
wrap_mode(wrap_mode),
lost(false),
@@ -695,7 +701,6 @@ ResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
}
ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() {
- resource_provider_->UnbindForSampling(resource_id_, target_, unit_);
}
ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
@@ -1343,23 +1348,14 @@ void ResourceProvider::BindForSampling(ResourceProvider::ResourceId resource_id,
resource->filter = filter;
}
- if (resource->image_id)
+ if (resource->image_id && resource->dirty_image) {
+ // Release image currently bound to texture.
+ if (resource->bound_image_id)
+ context3d->releaseTexImage2DCHROMIUM(target, resource->bound_image_id);
context3d->bindTexImage2DCHROMIUM(target, resource->image_id);
-}
-
-void ResourceProvider::UnbindForSampling(
- ResourceProvider::ResourceId resource_id, GLenum target, GLenum unit) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(resource_id);
- DCHECK(it != resources_.end());
- Resource* resource = &it->second;
-
- if (!resource->image_id)
- return;
-
- WebGraphicsContext3D* context3d = Context3d();
- ScopedSetActiveTexture scoped_active_tex(context3d, unit);
- context3d->releaseTexImage2DCHROMIUM(target, resource->image_id);
+ resource->bound_image_id = resource->image_id;
+ resource->dirty_image = false;
+ }
}
void ResourceProvider::BeginSetPixels(ResourceId id) {
@@ -1596,6 +1592,8 @@ void ResourceProvider::ReleaseImage(ResourceId id) {
DCHECK(context3d);
context3d->destroyImageCHROMIUM(resource->image_id);
resource->image_id = 0;
+ resource->bound_image_id = 0;
+ resource->dirty_image = false;
resource->allocated = false;
}
@@ -1627,6 +1625,7 @@ void ResourceProvider::UnmapImage(ResourceId id) {
WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
context3d->unmapImageCHROMIUM(resource->image_id);
+ resource->dirty_image = true;
}
}
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
index df17819..b8cb399 100644
--- a/cc/resources/resource_provider.h
+++ b/cc/resources/resource_provider.h
@@ -390,6 +390,8 @@ class CC_EXPORT ResourceProvider {
GLenum original_filter;
GLenum filter;
unsigned image_id;
+ unsigned bound_image_id;
+ bool dirty_image;
GLenum texture_pool;
GLint wrap_mode;
bool lost;
@@ -454,9 +456,6 @@ class CC_EXPORT ResourceProvider {
GLenum target,
GLenum unit,
GLenum filter);
- void UnbindForSampling(ResourceProvider::ResourceId resource_id,
- GLenum target,
- GLenum unit);
// Returns NULL if the output_surface_ does not have a ContextProvider.
WebKit::WebGraphicsContext3D* Context3d() const;
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index 64dcd7b..9b3e243 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -2419,9 +2419,30 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
.Times(1)
.RetiresOnSaturation();
+ {
+ ResourceProvider::ScopedSamplerGL lock_gl(
+ resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
+ EXPECT_EQ(kTextureId, lock_gl.texture_id());
+ }
+
+ EXPECT_CALL(*context, mapImageCHROMIUM(kImageId, GL_READ_WRITE))
+ .WillOnce(Return(dummy_mapped_buffer_address))
+ .RetiresOnSaturation();
+ resource_provider->MapImage(id);
+
+ EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
+ .Times(1)
+ .RetiresOnSaturation();
+ resource_provider->UnmapImage(id);
+
+ EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
+ .RetiresOnSaturation();
EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
+ .Times(1)
+ .RetiresOnSaturation();
EXPECT_CALL(*context, deleteTexture(kTextureId))
.Times(1)
.RetiresOnSaturation();
diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc
index aa30cd3..194fe37 100644
--- a/gpu/command_buffer/service/framebuffer_manager.cc
+++ b/gpu/command_buffer/service/framebuffer_manager.cc
@@ -93,7 +93,7 @@ class RenderbufferAttachment
return true;
}
- virtual void DetachFromFramebuffer() const OVERRIDE {
+ virtual void DetachFromFramebuffer(Framebuffer* framebuffer) const OVERRIDE {
// Nothing to do for renderbuffers.
}
@@ -197,8 +197,10 @@ class TextureAttachment
return texture_ref_->texture()->CanRenderTo();
}
- virtual void DetachFromFramebuffer() const OVERRIDE {
+ virtual void DetachFromFramebuffer(Framebuffer* framebuffer)
+ const OVERRIDE {
texture_ref_->texture()->DetachFromFramebuffer();
+ framebuffer->OnTextureRefDetached(texture_ref_.get());
}
virtual bool ValidForAttachmentType(
@@ -241,6 +243,10 @@ class TextureAttachment
DISALLOW_COPY_AND_ASSIGN(TextureAttachment);
};
+FramebufferManager::TextureDetachObserver::TextureDetachObserver() {}
+
+FramebufferManager::TextureDetachObserver::~TextureDetachObserver() {}
+
FramebufferManager::FramebufferManager(
uint32 max_draw_buffers, uint32 max_color_attachments)
: framebuffer_state_change_count_(1),
@@ -263,7 +269,7 @@ void Framebuffer::MarkAsDeleted() {
deleted_ = true;
while (!attachments_.empty()) {
Attachment* attachment = attachments_.begin()->second.get();
- attachment->DetachFromFramebuffer();
+ attachment->DetachFromFramebuffer(this);
attachments_.erase(attachments_.begin());
}
}
@@ -548,7 +554,7 @@ void Framebuffer::AttachRenderbuffer(
GLenum attachment, Renderbuffer* renderbuffer) {
const Attachment* a = GetAttachment(attachment);
if (a)
- a->DetachFromFramebuffer();
+ a->DetachFromFramebuffer(this);
if (renderbuffer) {
attachments_[attachment] = scoped_refptr<Attachment>(
new RenderbufferAttachment(renderbuffer));
@@ -563,7 +569,7 @@ void Framebuffer::AttachTexture(
GLint level, GLsizei samples) {
const Attachment* a = GetAttachment(attachment);
if (a)
- a->DetachFromFramebuffer();
+ a->DetachFromFramebuffer(this);
if (texture_ref) {
attachments_[attachment] = scoped_refptr<Attachment>(
new TextureAttachment(texture_ref, target, level, samples));
@@ -584,6 +590,10 @@ const Framebuffer::Attachment*
return NULL;
}
+void Framebuffer::OnTextureRefDetached(TextureRef* texture) {
+ manager_->OnTextureRefDetached(texture);
+}
+
bool FramebufferManager::GetClientId(
GLuint service_id, GLuint* client_id) const {
// This doesn't need to be fast. It's only used during slow queries.
@@ -621,6 +631,12 @@ bool FramebufferManager::IsComplete(
framebuffer_state_change_count_;
}
+void FramebufferManager::OnTextureRefDetached(TextureRef* texture) {
+ FOR_EACH_OBSERVER(TextureDetachObserver,
+ texture_detach_observers_,
+ OnTextureRefDetachedFromFramebuffer(texture));
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h
index 7955ac1..06a75b4 100644
--- a/gpu/command_buffer/service/framebuffer_manager.h
+++ b/gpu/command_buffer/service/framebuffer_manager.h
@@ -9,6 +9,7 @@
#include "base/containers/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/gpu_export.h"
@@ -41,7 +42,7 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> {
virtual bool IsRenderbuffer(
Renderbuffer* renderbuffer) const = 0;
virtual bool CanRenderTo() const = 0;
- virtual void DetachFromFramebuffer() const = 0;
+ virtual void DetachFromFramebuffer(Framebuffer* framebuffer) const = 0;
virtual bool ValidForAttachmentType(
GLenum attachment_type, uint32 max_color_attachments) = 0;
virtual void AddToSignature(
@@ -130,6 +131,8 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> {
return allow_framebuffer_combo_complete_map_;
}
+ void OnTextureRefDetached(TextureRef* texture);
+
private:
friend class FramebufferManager;
friend class base::RefCounted<Framebuffer>;
@@ -197,6 +200,17 @@ struct DecoderFramebufferState {
// so we can correctly clear them.
class GPU_EXPORT FramebufferManager {
public:
+ class GPU_EXPORT TextureDetachObserver {
+ public:
+ TextureDetachObserver();
+ virtual ~TextureDetachObserver();
+
+ virtual void OnTextureRefDetachedFromFramebuffer(TextureRef* texture) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureDetachObserver);
+ };
+
FramebufferManager(uint32 max_draw_buffers, uint32 max_color_attachments);
~FramebufferManager();
@@ -230,12 +244,22 @@ class GPU_EXPORT FramebufferManager {
(framebuffer_state_change_count_ + 1) | 0x80000000U;
}
+ void AddObserver(TextureDetachObserver* observer) {
+ texture_detach_observers_.AddObserver(observer);
+ }
+
+ void RemoveObserver(TextureDetachObserver* observer) {
+ texture_detach_observers_.RemoveObserver(observer);
+ }
+
private:
friend class Framebuffer;
void StartTracking(Framebuffer* framebuffer);
void StopTracking(Framebuffer* framebuffer);
+ void OnTextureRefDetached(TextureRef* texture);
+
// Info for each framebuffer in the system.
typedef base::hash_map<GLuint, scoped_refptr<Framebuffer> >
FramebufferMap;
@@ -254,6 +278,8 @@ class GPU_EXPORT FramebufferManager {
uint32 max_draw_buffers_;
uint32 max_color_attachments_;
+ ObserverList<TextureDetachObserver> texture_detach_observers_;
+
DISALLOW_COPY_AND_ASSIGN(FramebufferManager);
};
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index dd02c9c..5145daa 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -521,7 +521,8 @@ bool GLES2Decoder::IsAngle() {
// 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 {
@@ -642,6 +643,10 @@ class GLES2DecoderImpl : public GLES2Decoder {
virtual error::ContextLostReason GetContextLostReason() OVERRIDE;
+ // Overridden from FramebufferManager::TextureDetachObserver:
+ virtual void OnTextureRefDetachedFromFramebuffer(
+ TextureRef* texture) OVERRIDE;
+
private:
friend class ScopedFrameBufferBinder;
friend class ScopedResolvedFrameBufferBinder;
@@ -1377,9 +1382,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(
@@ -2472,6 +2482,8 @@ bool GLES2DecoderImpl::Initialize(
AsyncPixelTransferManager::Create(context.get()));
async_pixel_transfer_manager_->Initialize(texture_manager());
+ framebuffer_manager()->AddObserver(this);
+
return true;
}
@@ -3203,6 +3215,8 @@ void GLES2DecoderImpl::Destroy(bool have_context) {
// by the context group.
async_pixel_transfer_manager_.reset();
+ framebuffer_manager()->RemoveObserver(this);
+
if (group_.get()) {
group_->Destroy(this, have_context);
group_ = NULL;
@@ -4866,6 +4880,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);
@@ -4886,6 +4903,10 @@ void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) {
framebuffer_state_.clear_state_dirty = true;
}
+
+ if (texture_ref)
+ DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget);
+
OnFboChanged();
}
@@ -5723,11 +5744,43 @@ void GLES2DecoderImpl::UpdateStreamTextureIfNeeded(Texture* texture,
}
}
+void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
+ Texture* texture, GLenum textarget) {
+ // 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();
+ }
+ }
+}
+
+void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
+ Texture* texture, GLenum textarget) {
+ // 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();
+ }
+ }
+}
+
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;
}
@@ -5742,12 +5795,9 @@ 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))) {
+ if (!texture_ref || !texture_manager()->CanRender(texture_ref)) {
textures_set = true;
glActiveTexture(GL_TEXTURE0 + texture_unit_index);
glBindTexture(
@@ -5759,7 +5809,21 @@ 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();
+ gfx::GLImage* image = texture->GetLevelImage(texture->target(), 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?
}
@@ -5767,7 +5831,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();
@@ -5780,9 +5844,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.
@@ -5791,6 +5853,17 @@ 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();
+ gfx::GLImage* image = texture->GetLevelImage(texture->target(), 0);
+ if (image && !texture->IsAttachedToFramebuffer()) {
+ ScopedGLErrorSuppressor suppressor(
+ "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
+ glActiveTexture(GL_TEXTURE0 + texture_unit_index);
+ image->DidUseTexImage();
+ continue;
}
}
}
@@ -6133,7 +6206,7 @@ error::Error GLES2DecoderImpl::DoDrawArrays(
}
ProcessPendingQueries();
if (textures_set) {
- RestoreStateForNonRenderableTextures();
+ RestoreStateForTextures();
}
if (simulated_fixed_attribs) {
RestoreStateForSimulatedFixedAttribs();
@@ -6267,7 +6340,7 @@ error::Error GLES2DecoderImpl::DoDrawElements(
ProcessPendingQueries();
if (textures_set) {
- RestoreStateForNonRenderableTextures();
+ RestoreStateForTextures();
}
if (simulated_fixed_attribs) {
RestoreStateForSimulatedFixedAttribs();
@@ -9601,6 +9674,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) {
@@ -9633,6 +9708,8 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
unpack_premultiply_alpha_,
unpack_unpremultiply_alpha_);
}
+
+ DoDidUseTexImageIfNeeded(source_texture, source_texture->target());
}
static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) {
@@ -10298,6 +10375,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.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 72c2fcd..573ba6e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -7886,6 +7886,146 @@ TEST_F(GLES2DecoderTest, ReleaseTexImage2DCHROMIUM) {
EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL);
}
+class MockGLImage : public gfx::GLImage {
+ public:
+ MockGLImage() {}
+
+ // Overridden from gfx::GLImage:
+ MOCK_METHOD0(Destroy, void());
+ MOCK_METHOD0(GetSize, gfx::Size());
+ MOCK_METHOD0(BindTexImage, bool());
+ MOCK_METHOD0(ReleaseTexImage, void());
+ MOCK_METHOD0(WillUseTexImage, void());
+ MOCK_METHOD0(DidUseTexImage, void());
+
+ protected:
+ virtual ~MockGLImage() {}
+};
+
+TEST_F(GLES2DecoderWithShaderTest, UseTexImage) {
+ DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
+ DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ kSharedMemoryId, kSharedMemoryOffset);
+
+ TextureRef* texture_ref = group().texture_manager()->GetTexture(
+ client_texture_id_);
+ ASSERT_TRUE(texture_ref != NULL);
+ Texture* texture = texture_ref->texture();
+ EXPECT_EQ(kServiceTextureId, texture->service_id());
+
+ const int32 kImageId = 1;
+ scoped_refptr<MockGLImage> image(new MockGLImage);
+ group().image_manager()->AddImage(image.get(), kImageId);
+
+ // Bind image to texture.
+ EXPECT_CALL(*image, BindTexImage())
+ .Times(1)
+ .WillOnce(Return(true))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*image, GetSize())
+ .Times(1)
+ .WillOnce(Return(gfx::Size(1, 1)))
+ .RetiresOnSaturation();
+ // ScopedGLErrorSuppressor calls GetError on its constructor and destructor.
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ BindTexImage2DCHROMIUM bind_tex_image_2d_cmd;
+ bind_tex_image_2d_cmd.Init(GL_TEXTURE_2D, kImageId);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(bind_tex_image_2d_cmd));
+
+ AddExpectationsForSimulatedAttrib0(kNumVertices, 0);
+ SetupExpectationsForApplyingDefaultDirtyState();
+
+ // ScopedGLErrorSuppressor calls GetError on its constructor and destructor.
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0))
+ .Times(3)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*image, WillUseTexImage())
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*image, DidUseTexImage())
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
+ .Times(1)
+ .RetiresOnSaturation();
+ DrawArrays cmd;
+ cmd.Init(GL_TRIANGLES, 0, kNumVertices);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ DoBindFramebuffer(GL_FRAMEBUFFER, client_framebuffer_id_,
+ kServiceFramebufferId);
+ // ScopedGLErrorSuppressor calls GetError on its constructor and destructor.
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId))
+ .Times(2)
+ .RetiresOnSaturation();
+ // Image will be 'in use' as long as bound to a framebuffer.
+ EXPECT_CALL(*image, WillUseTexImage())
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, FramebufferTexture2DEXT(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ kServiceTextureId, 0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ FramebufferTexture2D fbtex_cmd;
+ fbtex_cmd.Init(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_,
+ 0);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(fbtex_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+ // ScopedGLErrorSuppressor calls GetError on its constructor and destructor.
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, FramebufferRenderbufferEXT(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+ kServiceRenderbufferId))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId))
+ .Times(2)
+ .RetiresOnSaturation();
+ // Image should no longer be 'in use' after being unbound from framebuffer.
+ EXPECT_CALL(*image, DidUseTexImage())
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ FramebufferRenderbuffer fbrb_cmd;
+ fbrb_cmd.Init(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+ client_renderbuffer_id_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(fbrb_cmd));
+}
+
TEST_F(GLES2DecoderManualInitTest, GpuMemoryManagerCHROMIUM) {
InitDecoder(
"GL_ARB_texture_rectangle", // extensions
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index 9684493..a7f32e0 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -80,6 +80,7 @@ TextureManager::~TextureManager() {
DCHECK_EQ(0, num_unrenderable_textures_);
DCHECK_EQ(0, num_unsafe_textures_);
DCHECK_EQ(0, num_uncleared_mips_);
+ DCHECK_EQ(0, num_images_);
}
void TextureManager::Destroy(bool have_context) {
@@ -118,6 +119,7 @@ Texture::Texture(GLuint service_id)
framebuffer_attachment_count_(0),
stream_texture_(false),
immutable_(false),
+ has_images_(false),
estimated_size_(0),
can_render_condition_(CAN_RENDER_ALWAYS) {
}
@@ -431,6 +433,29 @@ void Texture::UpdateCanRenderCondition() {
can_render_condition_ = can_render_condition;
}
+void Texture::UpdateHasImages() {
+ if (level_infos_.empty())
+ return;
+
+ bool has_images = false;
+ for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
+ for (size_t jj = 0; jj < level_infos_[ii].size(); ++jj) {
+ const Texture::LevelInfo& info = level_infos_[ii][jj];
+ if (info.image.get() != NULL) {
+ has_images = true;
+ break;
+ }
+ }
+ }
+
+ if (has_images_ == has_images)
+ return;
+ has_images_ = has_images;
+ int delta = has_images ? +1 : -1;
+ for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
+ (*it)->manager()->UpdateNumImages(delta);
+}
+
void Texture::IncAllFramebufferStateChangeCount() {
for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
(*it)->manager()->IncFramebufferStateChangeCount();
@@ -479,6 +504,7 @@ void Texture::SetLevelInfo(
Update(feature_info);
UpdateCleared();
UpdateCanRenderCondition();
+ UpdateHasImages();
if (IsAttachedToFramebuffer()) {
// TODO(gman): If textures tracked which framebuffers they were attached to
// we could just mark those framebuffers as not complete.
@@ -780,6 +806,7 @@ void Texture::SetLevelImage(
DCHECK_EQ(info.level, level);
info.image = image;
UpdateCanRenderCondition();
+ UpdateHasImages();
}
gfx::GLImage* Texture::GetLevelImage(
@@ -845,6 +872,7 @@ TextureManager::TextureManager(MemoryTracker* memory_tracker,
num_unrenderable_textures_(0),
num_unsafe_textures_(0),
num_uncleared_mips_(0),
+ num_images_(0),
texture_count_(0),
have_context_(true) {
for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
@@ -1130,6 +1158,8 @@ void TextureManager::StartTracking(TextureRef* ref) {
++num_unsafe_textures_;
if (!texture->CanRender(feature_info_.get()))
++num_unrenderable_textures_;
+ if (texture->HasImages())
+ ++num_images_;
}
void TextureManager::StopTracking(TextureRef* ref) {
@@ -1144,6 +1174,10 @@ void TextureManager::StopTracking(TextureRef* ref) {
}
--texture_count_;
+ if (texture->HasImages()) {
+ DCHECK_NE(0, num_images_);
+ --num_images_;
+ }
if (!texture->CanRender(feature_info_.get())) {
DCHECK_NE(0, num_unrenderable_textures_);
--num_unrenderable_textures_;
@@ -1237,10 +1271,14 @@ void TextureManager::UpdateCanRenderCondition(
++num_unrenderable_textures_;
}
+void TextureManager::UpdateNumImages(int delta) {
+ num_images_ += delta;
+ DCHECK_GE(num_images_, 0);
+}
+
void TextureManager::IncFramebufferStateChangeCount() {
if (framebuffer_manager_)
framebuffer_manager_->IncFramebufferStateChangeCount();
-
}
bool TextureManager::ValidateTextureParameters(
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index 0a6e776..3dabf6d 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -114,6 +114,10 @@ class GPU_EXPORT Texture {
// does not exist.
gfx::GLImage* GetLevelImage(GLint target, GLint level) const;
+ bool HasImages() const {
+ return has_images_;
+ }
+
// Returns true of the given dimensions are inside the dimensions of the
// level and if the format and type match the level.
bool ValidForTexture(
@@ -317,6 +321,10 @@ class GPU_EXPORT Texture {
// texture.
void UpdateCanRenderCondition();
+ // Updates the images count in all the managers referencing this
+ // texture.
+ void UpdateHasImages();
+
// Increment the framebuffer state change count in all the managers
// referencing this texture.
void IncAllFramebufferStateChangeCount();
@@ -378,6 +386,9 @@ class GPU_EXPORT Texture {
// or dimensions of the texture object can be made.
bool immutable_;
+ // Whether or not this texture has images.
+ bool has_images_;
+
// Size in bytes this texture is assumed to take in memory.
uint32 estimated_size_;
@@ -656,6 +667,10 @@ class GPU_EXPORT TextureManager {
return num_uncleared_mips_ > 0;
}
+ bool HaveImages() const {
+ return num_images_ > 0;
+ }
+
GLuint black_texture_id(GLenum target) const {
switch (target) {
case GL_SAMPLER_2D:
@@ -758,6 +773,7 @@ class GPU_EXPORT TextureManager {
void UpdateUnclearedMips(int delta);
void UpdateCanRenderCondition(Texture::CanRenderCondition old_condition,
Texture::CanRenderCondition new_condition);
+ void UpdateNumImages(int delta);
void IncFramebufferStateChangeCount();
MemoryTypeTracker* GetMemTracker(GLenum texture_pool);
@@ -781,6 +797,7 @@ class GPU_EXPORT TextureManager {
int num_unrenderable_textures_;
int num_unsafe_textures_;
int num_uncleared_mips_;
+ int num_images_;
// Counts the number of Textures allocated with 'this' as its manager.
// Allows to check no Texture will outlive this.
diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc
index 2f5f036..312adfd 100644
--- a/gpu/command_buffer/service/texture_manager_unittest.cc
+++ b/gpu/command_buffer/service/texture_manager_unittest.cc
@@ -2367,5 +2367,65 @@ TEST_F(SharedTextureTest, Memory) {
memory_tracker2_->GetSize(MemoryTracker::kUnmanaged));
}
+TEST_F(SharedTextureTest, Images) {
+ scoped_refptr<TextureRef> ref1 = texture_manager1_->CreateTexture(10, 10);
+ scoped_refptr<TextureRef> ref2 =
+ texture_manager2_->Consume(20, ref1->texture());
+
+ texture_manager1_->SetTarget(ref1.get(), GL_TEXTURE_2D);
+ texture_manager1_->SetLevelInfo(ref1.get(),
+ GL_TEXTURE_2D,
+ 1,
+ GL_RGBA,
+ 2,
+ 2,
+ 1,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ true);
+ EXPECT_FALSE(ref1->texture()->HasImages());
+ EXPECT_FALSE(ref2->texture()->HasImages());
+ EXPECT_FALSE(texture_manager1_->HaveImages());
+ EXPECT_FALSE(texture_manager2_->HaveImages());
+ texture_manager1_->SetLevelImage(ref1.get(),
+ GL_TEXTURE_2D,
+ 1,
+ gfx::GLImage::CreateGLImage(0).get());
+ EXPECT_TRUE(ref1->texture()->HasImages());
+ EXPECT_TRUE(ref2->texture()->HasImages());
+ EXPECT_TRUE(texture_manager1_->HaveImages());
+ EXPECT_TRUE(texture_manager2_->HaveImages());
+ texture_manager1_->SetLevelImage(ref1.get(),
+ GL_TEXTURE_2D,
+ 1,
+ gfx::GLImage::CreateGLImage(0).get());
+ EXPECT_TRUE(ref1->texture()->HasImages());
+ EXPECT_TRUE(ref2->texture()->HasImages());
+ EXPECT_TRUE(texture_manager1_->HaveImages());
+ EXPECT_TRUE(texture_manager2_->HaveImages());
+ texture_manager1_->SetLevelInfo(ref1.get(),
+ GL_TEXTURE_2D,
+ 1,
+ GL_RGBA,
+ 2,
+ 2,
+ 1,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ true);
+ EXPECT_FALSE(ref1->texture()->HasImages());
+ EXPECT_FALSE(ref2->texture()->HasImages());
+ EXPECT_FALSE(texture_manager1_->HaveImages());
+ EXPECT_FALSE(texture_manager1_->HaveImages());
+
+ EXPECT_CALL(*gl_, DeleteTextures(1, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ texture_manager1_->RemoveTexture(10);
+ texture_manager2_->RemoveTexture(20);
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/ui/gl/gl_image.cc b/ui/gl/gl_image.cc
index aaefb94..ff7eb56 100644
--- a/ui/gl/gl_image.cc
+++ b/ui/gl/gl_image.cc
@@ -19,6 +19,14 @@ void GLImage::ReleaseTexImage() {
NOTIMPLEMENTED();
}
+void GLImage::WillUseTexImage() {
+ NOTIMPLEMENTED();
+}
+
+void GLImage::DidUseTexImage() {
+ NOTIMPLEMENTED();
+}
+
GLImage::~GLImage() {}
} // namespace gfx
diff --git a/ui/gl/gl_image.h b/ui/gl/gl_image.h
index 8d59bc4..859966c 100644
--- a/ui/gl/gl_image.h
+++ b/ui/gl/gl_image.h
@@ -33,6 +33,12 @@ class GL_EXPORT GLImage : public base::RefCounted<GLImage> {
// Release image from texture currently bound to GL_TEXTURE_2D target.
virtual void ReleaseTexImage();
+ // Called before the texture is used for drawing.
+ virtual void WillUseTexImage();
+
+ // Called after the texture has been used for drawing.
+ virtual void DidUseTexImage();
+
// Create a GL image for a window.
static scoped_refptr<GLImage> CreateGLImage(gfx::PluginWindowHandle window);
diff --git a/ui/gl/gl_image_egl.cc b/ui/gl/gl_image_egl.cc
index 182117c..aeafc9a 100644
--- a/ui/gl/gl_image_egl.cc
+++ b/ui/gl/gl_image_egl.cc
@@ -11,7 +11,8 @@ namespace gfx {
GLImageEGL::GLImageEGL(gfx::Size size)
: egl_image_(EGL_NO_IMAGE_KHR),
- size_(size) {
+ size_(size),
+ in_use_(false) {
}
GLImageEGL::~GLImageEGL() {
@@ -40,25 +41,6 @@ bool GLImageEGL::Initialize(gfx::GpuMemoryBufferHandle buffer) {
return true;
}
-bool GLImageEGL::BindTexImage() {
- if (egl_image_ == EGL_NO_IMAGE_KHR) {
- LOG(ERROR) << "NULL EGLImage in BindTexImage";
- return false;
- }
-
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_);
-
- if (glGetError() != GL_NO_ERROR) {
- return false;
- }
-
- return true;
-}
-
-gfx::Size GLImageEGL::GetSize() {
- return size_;
-}
-
void GLImageEGL::Destroy() {
if (egl_image_ == EGL_NO_IMAGE_KHR)
return;
@@ -74,7 +56,40 @@ void GLImageEGL::Destroy() {
egl_image_ = EGL_NO_IMAGE_KHR;
}
+gfx::Size GLImageEGL::GetSize() {
+ return size_;
+}
+
+bool GLImageEGL::BindTexImage() {
+ if (egl_image_ == EGL_NO_IMAGE_KHR) {
+ LOG(ERROR) << "NULL EGLImage in BindTexImage";
+ return false;
+ }
+
+ // Defer ImageTargetTexture2D if not currently in use.
+ if (!in_use_)
+ return true;
+
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_);
+ DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ return true;
+}
+
void GLImageEGL::ReleaseTexImage() {
+ // Nothing to do here as image is released after each use.
+}
+
+void GLImageEGL::WillUseTexImage() {
+ DCHECK(egl_image_);
+ DCHECK(!in_use_);
+ in_use_ = true;
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_);
+ DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
+void GLImageEGL::DidUseTexImage() {
+ DCHECK(in_use_);
+ in_use_ = false;
char zero[4] = { 0, };
glTexImage2D(GL_TEXTURE_2D,
0,
diff --git a/ui/gl/gl_image_egl.h b/ui/gl/gl_image_egl.h
index 1c66bb9..2c64f4d 100644
--- a/ui/gl/gl_image_egl.h
+++ b/ui/gl/gl_image_egl.h
@@ -21,6 +21,8 @@ class GL_EXPORT GLImageEGL : public GLImage {
virtual gfx::Size GetSize() OVERRIDE;
virtual bool BindTexImage() OVERRIDE;
virtual void ReleaseTexImage() OVERRIDE;
+ virtual void WillUseTexImage() OVERRIDE;
+ virtual void DidUseTexImage() OVERRIDE;
protected:
virtual ~GLImageEGL();
@@ -28,6 +30,7 @@ class GL_EXPORT GLImageEGL : public GLImage {
private:
EGLImageKHR egl_image_;
gfx::Size size_;
+ bool in_use_;
DISALLOW_COPY_AND_ASSIGN(GLImageEGL);
};
diff --git a/ui/gl/gl_image_glx.cc b/ui/gl/gl_image_glx.cc
index 85254f3..739b4d4 100644
--- a/ui/gl/gl_image_glx.cc
+++ b/ui/gl/gl_image_glx.cc
@@ -52,6 +52,10 @@ GLImageGLX::GLImageGLX(gfx::PluginWindowHandle window)
glx_pixmap_(0) {
}
+GLImageGLX::~GLImageGLX() {
+ Destroy();
+}
+
bool GLImageGLX::Initialize() {
if (!GLSurfaceGLX::IsTextureFromPixmapSupported()) {
LOG(ERROR) << "GLX_EXT_texture_from_pixmap not supported.";
@@ -170,8 +174,10 @@ void GLImageGLX::ReleaseTexImage() {
glXReleaseTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT);
}
-GLImageGLX::~GLImageGLX() {
- Destroy();
+void GLImageGLX::WillUseTexImage() {
+}
+
+void GLImageGLX::DidUseTexImage() {
}
} // namespace gfx
diff --git a/ui/gl/gl_image_glx.h b/ui/gl/gl_image_glx.h
index bbdaa30..e1b9b4f 100644
--- a/ui/gl/gl_image_glx.h
+++ b/ui/gl/gl_image_glx.h
@@ -23,6 +23,8 @@ class GL_EXPORT GLImageGLX : public GLImage {
virtual gfx::Size GetSize() OVERRIDE;
virtual bool BindTexImage() OVERRIDE;
virtual void ReleaseTexImage() OVERRIDE;
+ virtual void WillUseTexImage() OVERRIDE;
+ virtual void DidUseTexImage() OVERRIDE;
protected:
virtual ~GLImageGLX();
diff --git a/ui/gl/gl_image_shm.cc b/ui/gl/gl_image_shm.cc
index 78e8164..5b182eb 100644
--- a/ui/gl/gl_image_shm.cc
+++ b/ui/gl/gl_image_shm.cc
@@ -40,6 +40,13 @@ bool GLImageShm::Initialize(gfx::GpuMemoryBufferHandle buffer) {
return true;
}
+void GLImageShm::Destroy() {
+}
+
+gfx::Size GLImageShm::GetSize() {
+ return size_;
+}
+
bool GLImageShm::BindTexImage() {
TRACE_EVENT0("gpu", "GLImageShm::BindTexImage");
DCHECK(shared_memory_);
@@ -82,14 +89,13 @@ bool GLImageShm::BindTexImage() {
return true;
}
-gfx::Size GLImageShm::GetSize() {
- return size_;
+void GLImageShm::ReleaseTexImage() {
}
-void GLImageShm::Destroy() {
+void GLImageShm::WillUseTexImage() {
}
-void GLImageShm::ReleaseTexImage() {
+void GLImageShm::DidUseTexImage() {
}
} // namespace gfx
diff --git a/ui/gl/gl_image_shm.h b/ui/gl/gl_image_shm.h
index ffdfc8b..d18938d 100644
--- a/ui/gl/gl_image_shm.h
+++ b/ui/gl/gl_image_shm.h
@@ -21,6 +21,8 @@ class GL_EXPORT GLImageShm : public GLImage {
virtual gfx::Size GetSize() OVERRIDE;
virtual bool BindTexImage() OVERRIDE;
virtual void ReleaseTexImage() OVERRIDE;
+ virtual void WillUseTexImage() OVERRIDE;
+ virtual void DidUseTexImage() OVERRIDE;
protected:
virtual ~GLImageShm();
diff --git a/ui/gl/gl_image_stub.cc b/ui/gl/gl_image_stub.cc
index 86efe6e..a1a8a85 100644
--- a/ui/gl/gl_image_stub.cc
+++ b/ui/gl/gl_image_stub.cc
@@ -6,6 +6,13 @@
namespace gfx {
+GLImageStub::GLImageStub() {
+}
+
+GLImageStub::~GLImageStub() {
+ Destroy();
+}
+
void GLImageStub::Destroy() {
}
@@ -20,6 +27,10 @@ bool GLImageStub::BindTexImage() {
void GLImageStub::ReleaseTexImage() {
}
-GLImageStub::~GLImageStub() {}
+void GLImageStub::WillUseTexImage() {
+}
+
+void GLImageStub::DidUseTexImage() {
+}
} // namespace gfx
diff --git a/ui/gl/gl_image_stub.h b/ui/gl/gl_image_stub.h
index 8b47358..ec232fa 100644
--- a/ui/gl/gl_image_stub.h
+++ b/ui/gl/gl_image_stub.h
@@ -12,11 +12,15 @@ namespace gfx {
// A GLImage that does nothing for unit tests.
class GL_EXPORT GLImageStub : public GLImage {
public:
+ GLImageStub();
+
// Implement GLImage.
virtual void Destroy() OVERRIDE;
virtual gfx::Size GetSize() OVERRIDE;
virtual bool BindTexImage() OVERRIDE;
virtual void ReleaseTexImage() OVERRIDE;
+ virtual void WillUseTexImage() OVERRIDE;
+ virtual void DidUseTexImage() OVERRIDE;
protected:
virtual ~GLImageStub();