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

Unified Diff: content/browser/renderer_host/compositing_iosurface_transformer_mac.cc

Issue 13749002: Cache OpenGL textures and other objects in CompositingIOSurfaceMac copy/transform code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/compositing_iosurface_transformer_mac.cc
diff --git a/content/browser/renderer_host/compositing_iosurface_transformer_mac.cc b/content/browser/renderer_host/compositing_iosurface_transformer_mac.cc
index da2ba6aec2b5aa8911cad2e60b6e8257961ba3d5..28090d4804b5da2dddc7cefaf22ba9c82b64a9ba 100644
--- a/content/browser/renderer_host/compositing_iosurface_transformer_mac.cc
+++ b/content/browser/renderer_host/compositing_iosurface_transformer_mac.cc
@@ -17,68 +17,11 @@ namespace content {
namespace {
-// Simple auto-delete scoping support for an owned Framebuffer object.
-class ScopedFramebuffer {
- public:
- ScopedFramebuffer() {
- glGenFramebuffersEXT(1, &name_);
- }
-
- ~ScopedFramebuffer() {
- if (name_ != 0u)
- glDeleteFramebuffersEXT(1, &name_);
- }
-
- bool is_valid() const { return name_ != 0u; }
- GLuint name() const { return name_; }
-
- private:
- GLuint name_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedFramebuffer);
+const GLenum kColorAttachments[] = {
+ GL_COLOR_ATTACHMENT0_EXT,
+ GL_COLOR_ATTACHMENT1_EXT
};
-// Simple auto-delete scoping support for an owned texture object.
-class ScopedTexture {
- public:
- ScopedTexture() : name_(0u) {}
- ScopedTexture(GLenum target, const gfx::Size& size);
-
- ~ScopedTexture() {
- if (name_ != 0u)
- glDeleteTextures(1, &name_);
- }
-
- bool is_valid() const { return name_ != 0u; }
- GLuint name() const { return name_; }
-
- void Reset(GLuint texture) {
- if (name_ != 0u)
- glDeleteTextures(1, &name_);
- name_ = texture;
- }
-
- GLuint Release() {
- GLuint ret = name_;
- name_ = 0u;
- return ret;
- }
-
- private:
- GLuint name_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedTexture);
-};
-
-ScopedTexture::ScopedTexture(GLenum target, const gfx::Size& size) {
- glGenTextures(1, &name_);
- glBindTexture(target, name_);
- glTexImage2D(target, 0, GL_RGBA, size.width(), size.height(), 0, GL_BGRA,
- GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
- DCHECK(glGetError() == GL_NO_ERROR);
- glBindTexture(target, 0u);
-}
-
// Set viewport and model/projection matrices for drawing to a framebuffer of
// size dst_size, with coordinates starting at (0, 0).
void SetTransformationsForOffScreenRendering(const gfx::Size& dst_size) {
@@ -146,11 +89,14 @@ CompositingIOSurfaceTransformer::CompositingIOSurfaceTransformer(
CompositingIOSurfaceShaderPrograms* shader_program_cache)
: texture_target_(texture_target),
src_texture_needs_y_flip_(src_texture_needs_y_flip),
- shader_program_cache_(shader_program_cache) {
+ shader_program_cache_(shader_program_cache),
+ frame_buffer_(0) {
DCHECK(texture_target_ == GL_TEXTURE_RECTANGLE_ARB)
<< "Fragment shaders currently only support RECTANGLE textures.";
DCHECK(shader_program_cache_);
+ memset(textures_, 0, sizeof(textures_));
+
// The RGB-to-YV12 transform requires that the driver/hardware supports
// multiple draw buffers.
GLint max_draw_buffers = 1;
@@ -159,6 +105,23 @@ CompositingIOSurfaceTransformer::CompositingIOSurfaceTransformer(
}
CompositingIOSurfaceTransformer::~CompositingIOSurfaceTransformer() {
+ for (int i = 0; i < NUM_CACHED_TEXTURES; ++i)
+ DCHECK_EQ(textures_[i], 0u) << "Failed to call ReleaseCachedGLObjects().";
+ DCHECK_EQ(frame_buffer_, 0u) << "Failed to call ReleaseCachedGLObjects().";
+}
+
+void CompositingIOSurfaceTransformer::ReleaseCachedGLObjects() {
+ for (int i = 0; i < NUM_CACHED_TEXTURES; ++i) {
+ if (textures_[i]) {
+ glDeleteTextures(1, &textures_[i]);
+ textures_[i] = 0;
+ texture_sizes_[i] = gfx::Size();
+ }
+ }
+ if (frame_buffer_) {
+ glDeleteFramebuffersEXT(1, &frame_buffer_);
+ frame_buffer_ = 0;
+ }
}
bool CompositingIOSurfaceTransformer::ResizeBilinear(
@@ -171,16 +134,14 @@ bool CompositingIOSurfaceTransformer::ResizeBilinear(
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
- ScopedTexture dst_texture(texture_target_, dst_size);
- if (!dst_texture.is_valid())
- return false;
-
- ScopedFramebuffer temp_frame_buffer;
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, temp_frame_buffer.name());
+ PrepareTexture(RGBA_OUTPUT, dst_size);
+ PrepareFramebuffer();
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frame_buffer_);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- texture_target_, dst_texture.name(), 0);
+ texture_target_, textures_[RGBA_OUTPUT], 0);
DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) ==
GL_FRAMEBUFFER_COMPLETE_EXT);
+ glDrawBuffers(1, kColorAttachments);
ncarter (slow) 2013/04/15 23:38:19 This seems unnecessary.
miu 2013/04/16 03:51:22 It probably is. I was just playing it safe. Done
glBindTexture(texture_target_, src_texture);
SetTextureParameters(
@@ -195,9 +156,11 @@ bool CompositingIOSurfaceTransformer::ResizeBilinear(
src_texture_needs_y_flip_,
dst_size.width(), dst_size.height());
glUseProgram(0);
- glBindTexture(texture_target_, 0u);
- *texture = dst_texture.Release();
+ glBindTexture(texture_target_, 0);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ *texture = textures_[RGBA_OUTPUT];
return true;
}
@@ -221,7 +184,7 @@ bool CompositingIOSurfaceTransformer::TransformRGBToYV12(
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
- // Allocate output textures for each plane, and the temporary one for the UUVV
+ // Resize output textures for each plane, and for the intermediate UUVV one
// that becomes an input into pass #2. |packed_y_size| is the size of the Y
// output texture, where its width is 1/4 the number of Y pixels because 4 Y
// pixels are packed into a single quad. |packed_uv_size| is half the size of
@@ -229,36 +192,22 @@ bool CompositingIOSurfaceTransformer::TransformRGBToYV12(
*packed_y_size = gfx::Size((dst_size.width() + 3) / 4, dst_size.height());
*packed_uv_size = gfx::Size((packed_y_size->width() + 1) / 2,
(packed_y_size->height() + 1) / 2);
- ScopedTexture temp_texture_y(texture_target_, *packed_y_size);
- if (!temp_texture_y.is_valid())
- return false;
- ScopedTexture temp_texture_u(texture_target_, *packed_uv_size);
- if (!temp_texture_u.is_valid())
- return false;
- ScopedTexture temp_texture_v(texture_target_, *packed_uv_size);
- if (!temp_texture_v.is_valid())
- return false;
-
- // Create a temporary texture for the UUVV that becomes an input into pass #2.
- ScopedTexture temp_texture_uuvv(texture_target_, *packed_y_size);
- if (!temp_texture_uuvv.is_valid())
- return false;
-
- // Create a temporary FBO for writing to the textures off-screen.
- ScopedFramebuffer temp_frame_buffer;
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, temp_frame_buffer.name());
+ PrepareTexture(Y_PLANE_OUTPUT, *packed_y_size);
+ PrepareTexture(UUVV_INTERMEDIATE, *packed_y_size);
+ PrepareTexture(U_PLANE_OUTPUT, *packed_uv_size);
+ PrepareTexture(V_PLANE_OUTPUT, *packed_uv_size);
/////////////////////////////////////////
// Pass 1: RGB --(scaled)--> YYYY + UUVV
+ PrepareFramebuffer();
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frame_buffer_);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- texture_target_, temp_texture_y.name(), 0);
+ texture_target_, textures_[Y_PLANE_OUTPUT], 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
- texture_target_, temp_texture_uuvv.name(), 0);
+ texture_target_, textures_[UUVV_INTERMEDIATE], 0);
DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) ==
GL_FRAMEBUFFER_COMPLETE_EXT);
- static const GLenum kAttachments[] =
- { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
- glDrawBuffers(2, kAttachments);
+ glDrawBuffers(2, kColorAttachments);
// Read from |src_texture|. Enable bilinear filtering only if scaling is
// required. The filtering will take place entirely in the first pass.
@@ -283,15 +232,15 @@ bool CompositingIOSurfaceTransformer::TransformRGBToYV12(
/////////////////////////////////////////
// Pass 2: UUVV -> UUUU + VVVV
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- texture_target_, temp_texture_u.name(), 0);
+ texture_target_, textures_[U_PLANE_OUTPUT], 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
- texture_target_, temp_texture_v.name(), 0);
+ texture_target_, textures_[V_PLANE_OUTPUT], 0);
DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) ==
GL_FRAMEBUFFER_COMPLETE_EXT);
- // Read from texture_uuvv. The second pass uses bilinear minification to
- // achieve vertical scaling, so enable it always.
- glBindTexture(texture_target_, temp_texture_uuvv.name());
+ // Read from the intermediate UUVV texture. The second pass uses bilinear
+ // minification to achieve vertical scaling, so enable it always.
+ glBindTexture(texture_target_, textures_[UUVV_INTERMEDIATE]);
SetTextureParameters(texture_target_, GL_LINEAR, GL_CLAMP_TO_EDGE);
// Use the second-pass shader program and draw the scene.
@@ -305,15 +254,46 @@ bool CompositingIOSurfaceTransformer::TransformRGBToYV12(
false,
packed_uv_size->width(), packed_uv_size->height());
glUseProgram(0);
- glBindTexture(texture_target_, 0);
// Before leaving, put back to drawing to a single rendering output.
- glDrawBuffers(1, kAttachments);
+ glDrawBuffers(1, kColorAttachments);
- *texture_y = temp_texture_y.Release();
- *texture_u = temp_texture_u.Release();
- *texture_v = temp_texture_v.Release();
+ glBindTexture(texture_target_, 0);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ *texture_y = textures_[Y_PLANE_OUTPUT];
+ *texture_u = textures_[U_PLANE_OUTPUT];
+ *texture_v = textures_[V_PLANE_OUTPUT];
return true;
}
+void CompositingIOSurfaceTransformer::PrepareTexture(
+ CachedTexture which, const gfx::Size& size) {
+ DCHECK_GE(which, 0);
+ DCHECK_LT(which, NUM_CACHED_TEXTURES);
+ DCHECK(!size.IsEmpty());
+
+ if (!textures_[which]) {
+ glGenTextures(1, &textures_[which]);
+ DCHECK_NE(textures_[which], 0u);
+ texture_sizes_[which] = gfx::Size();
+ }
+
+ // Re-allocate the texture if its size has changed since last use.
+ if (texture_sizes_[which] != size) {
ncarter (slow) 2013/04/15 23:38:19 Might be worth TRACE_EVENTING this since it should
miu 2013/04/16 03:51:22 Done. Good call.
+ glBindTexture(texture_target_, textures_[which]);
+ glTexImage2D(texture_target_, 0, GL_RGBA, size.width(), size.height(), 0,
+ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
+ DCHECK(glGetError() == GL_NO_ERROR);
ncarter (slow) 2013/04/15 23:38:19 Why DCHECK glGetError() here specifically (is this
miu 2013/04/16 03:51:22 Done. Yep. Leftover debugging cruft. I had a pr
+ texture_sizes_[which] = size;
+ }
+}
+
+void CompositingIOSurfaceTransformer::PrepareFramebuffer() {
+ if (!frame_buffer_) {
+ glGenFramebuffersEXT(1, &frame_buffer_);
+ DCHECK_NE(frame_buffer_, 0u);
+ }
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698