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

Side by Side 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: Tweaks, per nick@'s comments. 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/compositing_iosurface_transformer_mac.h" 5 #include "content/browser/renderer_host/compositing_iosurface_transformer_mac.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "content/browser/renderer_host/compositing_iosurface_shader_programs_ma c.h" 12 #include "content/browser/renderer_host/compositing_iosurface_shader_programs_ma c.h"
13 #include "ui/gfx/rect.h" 13 #include "ui/gfx/rect.h"
14 #include "ui/gfx/size.h" 14 #include "ui/gfx/size.h"
15 15
16 namespace content { 16 namespace content {
17 17
18 namespace { 18 namespace {
19 19
20 // Simple auto-delete scoping support for an owned Framebuffer object. 20 const GLenum kColorAttachments[] = {
21 class ScopedFramebuffer { 21 GL_COLOR_ATTACHMENT0_EXT,
22 public: 22 GL_COLOR_ATTACHMENT1_EXT
23 ScopedFramebuffer() {
24 glGenFramebuffersEXT(1, &name_);
25 }
26
27 ~ScopedFramebuffer() {
28 if (name_ != 0u)
29 glDeleteFramebuffersEXT(1, &name_);
30 }
31
32 bool is_valid() const { return name_ != 0u; }
33 GLuint name() const { return name_; }
34
35 private:
36 GLuint name_;
37
38 DISALLOW_COPY_AND_ASSIGN(ScopedFramebuffer);
39 }; 23 };
40 24
41 // Simple auto-delete scoping support for an owned texture object.
42 class ScopedTexture {
43 public:
44 ScopedTexture() : name_(0u) {}
45 ScopedTexture(GLenum target, const gfx::Size& size);
46
47 ~ScopedTexture() {
48 if (name_ != 0u)
49 glDeleteTextures(1, &name_);
50 }
51
52 bool is_valid() const { return name_ != 0u; }
53 GLuint name() const { return name_; }
54
55 void Reset(GLuint texture) {
56 if (name_ != 0u)
57 glDeleteTextures(1, &name_);
58 name_ = texture;
59 }
60
61 GLuint Release() {
62 GLuint ret = name_;
63 name_ = 0u;
64 return ret;
65 }
66
67 private:
68 GLuint name_;
69
70 DISALLOW_COPY_AND_ASSIGN(ScopedTexture);
71 };
72
73 ScopedTexture::ScopedTexture(GLenum target, const gfx::Size& size) {
74 glGenTextures(1, &name_);
75 glBindTexture(target, name_);
76 glTexImage2D(target, 0, GL_RGBA, size.width(), size.height(), 0, GL_BGRA,
77 GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
78 DCHECK(glGetError() == GL_NO_ERROR);
79 glBindTexture(target, 0u);
80 }
81
82 // Set viewport and model/projection matrices for drawing to a framebuffer of 25 // Set viewport and model/projection matrices for drawing to a framebuffer of
83 // size dst_size, with coordinates starting at (0, 0). 26 // size dst_size, with coordinates starting at (0, 0).
84 void SetTransformationsForOffScreenRendering(const gfx::Size& dst_size) { 27 void SetTransformationsForOffScreenRendering(const gfx::Size& dst_size) {
85 glViewport(0, 0, dst_size.width(), dst_size.height()); 28 glViewport(0, 0, dst_size.width(), dst_size.height());
86 glMatrixMode(GL_PROJECTION); 29 glMatrixMode(GL_PROJECTION);
87 glLoadIdentity(); 30 glLoadIdentity();
88 glOrtho(0, dst_size.width(), 0, dst_size.height(), -1, 1); 31 glOrtho(0, dst_size.width(), 0, dst_size.height(), -1, 1);
89 glMatrixMode(GL_MODELVIEW); 32 glMatrixMode(GL_MODELVIEW);
90 glLoadIdentity(); 33 glLoadIdentity();
91 } 34 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 82 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
140 } 83 }
141 84
142 } // namespace 85 } // namespace
143 86
144 CompositingIOSurfaceTransformer::CompositingIOSurfaceTransformer( 87 CompositingIOSurfaceTransformer::CompositingIOSurfaceTransformer(
145 GLenum texture_target, bool src_texture_needs_y_flip, 88 GLenum texture_target, bool src_texture_needs_y_flip,
146 CompositingIOSurfaceShaderPrograms* shader_program_cache) 89 CompositingIOSurfaceShaderPrograms* shader_program_cache)
147 : texture_target_(texture_target), 90 : texture_target_(texture_target),
148 src_texture_needs_y_flip_(src_texture_needs_y_flip), 91 src_texture_needs_y_flip_(src_texture_needs_y_flip),
149 shader_program_cache_(shader_program_cache) { 92 shader_program_cache_(shader_program_cache),
93 frame_buffer_(0) {
150 DCHECK(texture_target_ == GL_TEXTURE_RECTANGLE_ARB) 94 DCHECK(texture_target_ == GL_TEXTURE_RECTANGLE_ARB)
151 << "Fragment shaders currently only support RECTANGLE textures."; 95 << "Fragment shaders currently only support RECTANGLE textures.";
152 DCHECK(shader_program_cache_); 96 DCHECK(shader_program_cache_);
153 97
98 memset(textures_, 0, sizeof(textures_));
99
154 // The RGB-to-YV12 transform requires that the driver/hardware supports 100 // The RGB-to-YV12 transform requires that the driver/hardware supports
155 // multiple draw buffers. 101 // multiple draw buffers.
156 GLint max_draw_buffers = 1; 102 GLint max_draw_buffers = 1;
157 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers); 103 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers);
158 system_supports_multiple_draw_buffers_ = (max_draw_buffers >= 2); 104 system_supports_multiple_draw_buffers_ = (max_draw_buffers >= 2);
159 } 105 }
160 106
161 CompositingIOSurfaceTransformer::~CompositingIOSurfaceTransformer() { 107 CompositingIOSurfaceTransformer::~CompositingIOSurfaceTransformer() {
108 for (int i = 0; i < NUM_CACHED_TEXTURES; ++i)
109 DCHECK_EQ(textures_[i], 0u) << "Failed to call ReleaseCachedGLObjects().";
110 DCHECK_EQ(frame_buffer_, 0u) << "Failed to call ReleaseCachedGLObjects().";
111 }
112
113 void CompositingIOSurfaceTransformer::ReleaseCachedGLObjects() {
114 for (int i = 0; i < NUM_CACHED_TEXTURES; ++i) {
115 if (textures_[i]) {
116 glDeleteTextures(1, &textures_[i]);
117 textures_[i] = 0;
118 texture_sizes_[i] = gfx::Size();
119 }
120 }
121 if (frame_buffer_) {
122 glDeleteFramebuffersEXT(1, &frame_buffer_);
123 frame_buffer_ = 0;
124 }
162 } 125 }
163 126
164 bool CompositingIOSurfaceTransformer::ResizeBilinear( 127 bool CompositingIOSurfaceTransformer::ResizeBilinear(
165 GLuint src_texture, const gfx::Rect& src_subrect, const gfx::Size& dst_size, 128 GLuint src_texture, const gfx::Rect& src_subrect, const gfx::Size& dst_size,
166 GLuint* texture) { 129 GLuint* texture) {
167 if (src_subrect.IsEmpty() || dst_size.IsEmpty()) 130 if (src_subrect.IsEmpty() || dst_size.IsEmpty())
168 return false; 131 return false;
169 132
170 glActiveTexture(GL_TEXTURE0); 133 glActiveTexture(GL_TEXTURE0);
171 glDisable(GL_DEPTH_TEST); 134 glDisable(GL_DEPTH_TEST);
172 glDisable(GL_BLEND); 135 glDisable(GL_BLEND);
173 136
174 ScopedTexture dst_texture(texture_target_, dst_size); 137 PrepareTexture(RGBA_OUTPUT, dst_size);
175 if (!dst_texture.is_valid()) 138 PrepareFramebuffer();
176 return false; 139 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frame_buffer_);
177
178 ScopedFramebuffer temp_frame_buffer;
179 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, temp_frame_buffer.name());
180 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 140 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
181 texture_target_, dst_texture.name(), 0); 141 texture_target_, textures_[RGBA_OUTPUT], 0);
182 DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == 142 DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) ==
183 GL_FRAMEBUFFER_COMPLETE_EXT); 143 GL_FRAMEBUFFER_COMPLETE_EXT);
184 144
185 glBindTexture(texture_target_, src_texture); 145 glBindTexture(texture_target_, src_texture);
186 SetTextureParameters( 146 SetTextureParameters(
187 texture_target_, src_subrect.size() == dst_size ? GL_NEAREST : GL_LINEAR, 147 texture_target_, src_subrect.size() == dst_size ? GL_NEAREST : GL_LINEAR,
188 GL_CLAMP_TO_EDGE); 148 GL_CLAMP_TO_EDGE);
189 149
190 const bool prepared = shader_program_cache_->UseBlitProgram(); 150 const bool prepared = shader_program_cache_->UseBlitProgram();
191 DCHECK(prepared); 151 DCHECK(prepared);
192 SetTransformationsForOffScreenRendering(dst_size); 152 SetTransformationsForOffScreenRendering(dst_size);
193 DrawQuad(src_subrect.x(), src_subrect.y(), 153 DrawQuad(src_subrect.x(), src_subrect.y(),
194 src_subrect.width(), src_subrect.height(), 154 src_subrect.width(), src_subrect.height(),
195 src_texture_needs_y_flip_, 155 src_texture_needs_y_flip_,
196 dst_size.width(), dst_size.height()); 156 dst_size.width(), dst_size.height());
197 glUseProgram(0); 157 glUseProgram(0);
198 glBindTexture(texture_target_, 0u);
199 158
200 *texture = dst_texture.Release(); 159 glBindTexture(texture_target_, 0);
160 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
161
162 *texture = textures_[RGBA_OUTPUT];
201 return true; 163 return true;
202 } 164 }
203 165
204 bool CompositingIOSurfaceTransformer::TransformRGBToYV12( 166 bool CompositingIOSurfaceTransformer::TransformRGBToYV12(
205 GLuint src_texture, 167 GLuint src_texture,
206 const gfx::Rect& src_subrect, 168 const gfx::Rect& src_subrect,
207 const gfx::Size& dst_size, 169 const gfx::Size& dst_size,
208 GLuint* texture_y, 170 GLuint* texture_y,
209 GLuint* texture_u, 171 GLuint* texture_u,
210 GLuint* texture_v, 172 GLuint* texture_v,
211 gfx::Size* packed_y_size, 173 gfx::Size* packed_y_size,
212 gfx::Size* packed_uv_size) { 174 gfx::Size* packed_uv_size) {
213 if (!system_supports_multiple_draw_buffers_) 175 if (!system_supports_multiple_draw_buffers_)
214 return false; 176 return false;
215 if (src_subrect.IsEmpty() || dst_size.IsEmpty()) 177 if (src_subrect.IsEmpty() || dst_size.IsEmpty())
216 return false; 178 return false;
217 179
218 TRACE_EVENT0("gpu", "TransformRGBToYV12"); 180 TRACE_EVENT0("gpu", "TransformRGBToYV12");
219 181
220 glActiveTexture(GL_TEXTURE0); 182 glActiveTexture(GL_TEXTURE0);
221 glDisable(GL_DEPTH_TEST); 183 glDisable(GL_DEPTH_TEST);
222 glDisable(GL_BLEND); 184 glDisable(GL_BLEND);
223 185
224 // Allocate output textures for each plane, and the temporary one for the UUVV 186 // Resize output textures for each plane, and for the intermediate UUVV one
225 // that becomes an input into pass #2. |packed_y_size| is the size of the Y 187 // that becomes an input into pass #2. |packed_y_size| is the size of the Y
226 // output texture, where its width is 1/4 the number of Y pixels because 4 Y 188 // output texture, where its width is 1/4 the number of Y pixels because 4 Y
227 // pixels are packed into a single quad. |packed_uv_size| is half the size of 189 // pixels are packed into a single quad. |packed_uv_size| is half the size of
228 // Y in both dimensions, rounded up. 190 // Y in both dimensions, rounded up.
229 *packed_y_size = gfx::Size((dst_size.width() + 3) / 4, dst_size.height()); 191 *packed_y_size = gfx::Size((dst_size.width() + 3) / 4, dst_size.height());
230 *packed_uv_size = gfx::Size((packed_y_size->width() + 1) / 2, 192 *packed_uv_size = gfx::Size((packed_y_size->width() + 1) / 2,
231 (packed_y_size->height() + 1) / 2); 193 (packed_y_size->height() + 1) / 2);
232 ScopedTexture temp_texture_y(texture_target_, *packed_y_size); 194 PrepareTexture(Y_PLANE_OUTPUT, *packed_y_size);
233 if (!temp_texture_y.is_valid()) 195 PrepareTexture(UUVV_INTERMEDIATE, *packed_y_size);
234 return false; 196 PrepareTexture(U_PLANE_OUTPUT, *packed_uv_size);
235 ScopedTexture temp_texture_u(texture_target_, *packed_uv_size); 197 PrepareTexture(V_PLANE_OUTPUT, *packed_uv_size);
236 if (!temp_texture_u.is_valid())
237 return false;
238 ScopedTexture temp_texture_v(texture_target_, *packed_uv_size);
239 if (!temp_texture_v.is_valid())
240 return false;
241
242 // Create a temporary texture for the UUVV that becomes an input into pass #2.
243 ScopedTexture temp_texture_uuvv(texture_target_, *packed_y_size);
244 if (!temp_texture_uuvv.is_valid())
245 return false;
246
247 // Create a temporary FBO for writing to the textures off-screen.
248 ScopedFramebuffer temp_frame_buffer;
249 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, temp_frame_buffer.name());
250 198
251 ///////////////////////////////////////// 199 /////////////////////////////////////////
252 // Pass 1: RGB --(scaled)--> YYYY + UUVV 200 // Pass 1: RGB --(scaled)--> YYYY + UUVV
201 PrepareFramebuffer();
202 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frame_buffer_);
253 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 203 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
254 texture_target_, temp_texture_y.name(), 0); 204 texture_target_, textures_[Y_PLANE_OUTPUT], 0);
255 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, 205 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
256 texture_target_, temp_texture_uuvv.name(), 0); 206 texture_target_, textures_[UUVV_INTERMEDIATE], 0);
257 DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == 207 DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) ==
258 GL_FRAMEBUFFER_COMPLETE_EXT); 208 GL_FRAMEBUFFER_COMPLETE_EXT);
259 static const GLenum kAttachments[] = 209 glDrawBuffers(2, kColorAttachments);
260 { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
261 glDrawBuffers(2, kAttachments);
262 210
263 // Read from |src_texture|. Enable bilinear filtering only if scaling is 211 // Read from |src_texture|. Enable bilinear filtering only if scaling is
264 // required. The filtering will take place entirely in the first pass. 212 // required. The filtering will take place entirely in the first pass.
265 glBindTexture(texture_target_, src_texture); 213 glBindTexture(texture_target_, src_texture);
266 SetTextureParameters( 214 SetTextureParameters(
267 texture_target_, src_subrect.size() == dst_size ? GL_NEAREST : GL_LINEAR, 215 texture_target_, src_subrect.size() == dst_size ? GL_NEAREST : GL_LINEAR,
268 GL_CLAMP_TO_EDGE); 216 GL_CLAMP_TO_EDGE);
269 217
270 // Use the first-pass shader program and draw the scene. 218 // Use the first-pass shader program and draw the scene.
271 const bool prepared_pass_1 = shader_program_cache_->UseRGBToYV12Program( 219 const bool prepared_pass_1 = shader_program_cache_->UseRGBToYV12Program(
272 1, 220 1,
273 static_cast<float>(src_subrect.width()) / dst_size.width()); 221 static_cast<float>(src_subrect.width()) / dst_size.width());
274 DCHECK(prepared_pass_1); 222 DCHECK(prepared_pass_1);
275 SetTransformationsForOffScreenRendering(*packed_y_size); 223 SetTransformationsForOffScreenRendering(*packed_y_size);
276 DrawQuad(src_subrect.x(), src_subrect.y(), 224 DrawQuad(src_subrect.x(), src_subrect.y(),
277 ((packed_y_size->width() * 4.0f) / dst_size.width()) * 225 ((packed_y_size->width() * 4.0f) / dst_size.width()) *
278 src_subrect.width(), 226 src_subrect.width(),
279 src_subrect.height(), 227 src_subrect.height(),
280 src_texture_needs_y_flip_, 228 src_texture_needs_y_flip_,
281 packed_y_size->width(), packed_y_size->height()); 229 packed_y_size->width(), packed_y_size->height());
282 230
283 ///////////////////////////////////////// 231 /////////////////////////////////////////
284 // Pass 2: UUVV -> UUUU + VVVV 232 // Pass 2: UUVV -> UUUU + VVVV
285 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 233 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
286 texture_target_, temp_texture_u.name(), 0); 234 texture_target_, textures_[U_PLANE_OUTPUT], 0);
287 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, 235 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
288 texture_target_, temp_texture_v.name(), 0); 236 texture_target_, textures_[V_PLANE_OUTPUT], 0);
289 DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == 237 DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) ==
290 GL_FRAMEBUFFER_COMPLETE_EXT); 238 GL_FRAMEBUFFER_COMPLETE_EXT);
291 239
292 // Read from texture_uuvv. The second pass uses bilinear minification to 240 // Read from the intermediate UUVV texture. The second pass uses bilinear
293 // achieve vertical scaling, so enable it always. 241 // minification to achieve vertical scaling, so enable it always.
294 glBindTexture(texture_target_, temp_texture_uuvv.name()); 242 glBindTexture(texture_target_, textures_[UUVV_INTERMEDIATE]);
295 SetTextureParameters(texture_target_, GL_LINEAR, GL_CLAMP_TO_EDGE); 243 SetTextureParameters(texture_target_, GL_LINEAR, GL_CLAMP_TO_EDGE);
296 244
297 // Use the second-pass shader program and draw the scene. 245 // Use the second-pass shader program and draw the scene.
298 const bool prepared_pass_2 = 246 const bool prepared_pass_2 =
299 shader_program_cache_->UseRGBToYV12Program(2, 1.0f); 247 shader_program_cache_->UseRGBToYV12Program(2, 1.0f);
300 DCHECK(prepared_pass_2); 248 DCHECK(prepared_pass_2);
301 SetTransformationsForOffScreenRendering(*packed_uv_size); 249 SetTransformationsForOffScreenRendering(*packed_uv_size);
302 DrawQuad(0.0f, 0.0f, 250 DrawQuad(0.0f, 0.0f,
303 packed_uv_size->width() * 2.0f, 251 packed_uv_size->width() * 2.0f,
304 packed_uv_size->height() * 2.0f, 252 packed_uv_size->height() * 2.0f,
305 false, 253 false,
306 packed_uv_size->width(), packed_uv_size->height()); 254 packed_uv_size->width(), packed_uv_size->height());
307 glUseProgram(0); 255 glUseProgram(0);
308 glBindTexture(texture_target_, 0);
309 256
310 // Before leaving, put back to drawing to a single rendering output. 257 // Before leaving, put back to drawing to a single rendering output.
311 glDrawBuffers(1, kAttachments); 258 glDrawBuffers(1, kColorAttachments);
312 259
313 *texture_y = temp_texture_y.Release(); 260 glBindTexture(texture_target_, 0);
314 *texture_u = temp_texture_u.Release(); 261 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
315 *texture_v = temp_texture_v.Release(); 262
263 *texture_y = textures_[Y_PLANE_OUTPUT];
264 *texture_u = textures_[U_PLANE_OUTPUT];
265 *texture_v = textures_[V_PLANE_OUTPUT];
316 return true; 266 return true;
317 } 267 }
318 268
269 void CompositingIOSurfaceTransformer::PrepareTexture(
270 CachedTexture which, const gfx::Size& size) {
271 DCHECK_GE(which, 0);
272 DCHECK_LT(which, NUM_CACHED_TEXTURES);
273 DCHECK(!size.IsEmpty());
274
275 if (!textures_[which]) {
276 glGenTextures(1, &textures_[which]);
277 DCHECK_NE(textures_[which], 0u);
278 texture_sizes_[which] = gfx::Size();
279 }
280
281 // Re-allocate the texture if its size has changed since last use.
282 if (texture_sizes_[which] != size) {
283 TRACE_EVENT2("gpu", "Resize Texture",
284 "which", which,
285 "new_size", size.ToString());
286 glBindTexture(texture_target_, textures_[which]);
287 glTexImage2D(texture_target_, 0, GL_RGBA, size.width(), size.height(), 0,
288 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
289 texture_sizes_[which] = size;
290 }
291 }
292
293 void CompositingIOSurfaceTransformer::PrepareFramebuffer() {
294 if (!frame_buffer_) {
295 glGenFramebuffersEXT(1, &frame_buffer_);
296 DCHECK_NE(frame_buffer_, 0u);
297 }
298 }
299
319 } // namespace content 300 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698