Remove wpr.archive_info dependancy on page to avoid circular dependancies.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_copy_texture_chromium.cc
blobd41ee9db3a30a062d461981c4581274eb63ba8b2
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
7 #include <algorithm>
9 #include "base/basictypes.h"
10 #include "gpu/command_buffer/service/gl_utils.h"
11 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
13 #define SHADER(src) \
14 "#ifdef GL_ES\n" \
15 "precision mediump float;\n" \
16 "#define TexCoordPrecision mediump\n" \
17 "#else\n" \
18 "#define TexCoordPrecision\n" \
19 "#endif\n" #src
20 #define SHADER_2D(src) \
21 "#define SamplerType sampler2D\n" \
22 "#define TextureLookup texture2D\n" SHADER(src)
23 #define SHADER_RECTANGLE_ARB(src) \
24 "#define SamplerType sampler2DRect\n" \
25 "#define TextureLookup texture2DRect\n" SHADER(src)
26 #define SHADER_EXTERNAL_OES(src) \
27 "#extension GL_OES_EGL_image_external : require\n" \
28 "#define SamplerType samplerExternalOES\n" \
29 "#define TextureLookup texture2D\n" SHADER(src)
30 #define FRAGMENT_SHADERS(src) \
31 SHADER_2D(src), SHADER_RECTANGLE_ARB(src), SHADER_EXTERNAL_OES(src)
33 namespace {
35 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
36 0.0f, 1.0f, 0.0f, 0.0f,
37 0.0f, 0.0f, 1.0f, 0.0f,
38 0.0f, 0.0f, 0.0f, 1.0f};
40 enum VertexShaderId {
41 VERTEX_SHADER_COPY_TEXTURE,
42 VERTEX_SHADER_COPY_TEXTURE_FLIP_Y,
43 NUM_VERTEX_SHADERS,
46 enum FragmentShaderId {
47 FRAGMENT_SHADER_COPY_TEXTURE_2D,
48 FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB,
49 FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES,
50 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D,
51 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_RECTANGLE_ARB,
52 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES,
53 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D,
54 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_RECTANGLE_ARB,
55 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES,
56 NUM_FRAGMENT_SHADERS,
59 const char* vertex_shader_source[NUM_VERTEX_SHADERS] = {
60 // VERTEX_SHADER_COPY_TEXTURE
61 SHADER(
62 uniform mat4 u_matrix;
63 uniform vec2 u_half_size;
64 attribute vec4 a_position;
65 varying TexCoordPrecision vec2 v_uv;
66 void main(void) {
67 gl_Position = u_matrix * a_position;
68 v_uv = a_position.xy * vec2(u_half_size.s, u_half_size.t) +
69 vec2(u_half_size.s, u_half_size.t);
70 }),
71 // VERTEX_SHADER_COPY_TEXTURE_FLIP_Y
72 SHADER(
73 uniform mat4 u_matrix;
74 uniform vec2 u_half_size;
75 attribute vec4 a_position;
76 varying TexCoordPrecision vec2 v_uv;
77 void main(void) {
78 gl_Position = u_matrix * a_position;
79 v_uv = a_position.xy * vec2(u_half_size.s, -u_half_size.t) +
80 vec2(u_half_size.s, u_half_size.t);
81 }),
84 const char* fragment_shader_source[NUM_FRAGMENT_SHADERS] = {
85 // FRAGMENT_SHADER_COPY_TEXTURE_*
86 FRAGMENT_SHADERS(
87 uniform SamplerType u_sampler;
88 varying TexCoordPrecision vec2 v_uv;
89 void main(void) {
90 gl_FragColor = TextureLookup(u_sampler, v_uv.st);
91 }),
92 // FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_*
93 FRAGMENT_SHADERS(
94 uniform SamplerType u_sampler;
95 varying TexCoordPrecision vec2 v_uv;
96 void main(void) {
97 gl_FragColor = TextureLookup(u_sampler, v_uv.st);
98 gl_FragColor.rgb *= gl_FragColor.a;
99 }),
100 // FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_*
101 FRAGMENT_SHADERS(
102 uniform SamplerType u_sampler;
103 varying TexCoordPrecision vec2 v_uv;
104 void main(void) {
105 gl_FragColor = TextureLookup(u_sampler, v_uv.st);
106 if (gl_FragColor.a > 0.0)
107 gl_FragColor.rgb /= gl_FragColor.a;
111 // Returns the correct vertex shader id to evaluate the copy operation for
112 // the CHROMIUM_flipy setting.
113 VertexShaderId GetVertexShaderId(bool flip_y) {
114 // bit 0: flip y
115 static VertexShaderId shader_ids[] = {
116 VERTEX_SHADER_COPY_TEXTURE,
117 VERTEX_SHADER_COPY_TEXTURE_FLIP_Y,
120 unsigned index = flip_y ? 1 : 0;
121 return shader_ids[index];
124 // Returns the correct fragment shader id to evaluate the copy operation for
125 // the premultiply alpha pixel store settings and target.
126 FragmentShaderId GetFragmentShaderId(bool premultiply_alpha,
127 bool unpremultiply_alpha,
128 GLenum target) {
129 enum {
130 SAMPLER_2D,
131 SAMPLER_RECTANGLE_ARB,
132 SAMPLER_EXTERNAL_OES,
133 NUM_SAMPLERS
136 // bit 0: premultiply alpha
137 // bit 1: unpremultiply alpha
138 static FragmentShaderId shader_ids[][NUM_SAMPLERS] = {
140 FRAGMENT_SHADER_COPY_TEXTURE_2D,
141 FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB,
142 FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES,
145 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D,
146 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_RECTANGLE_ARB,
147 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES,
150 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D,
151 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_RECTANGLE_ARB,
152 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES,
155 FRAGMENT_SHADER_COPY_TEXTURE_2D,
156 FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB,
157 FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES,
160 unsigned index = (premultiply_alpha ? (1 << 0) : 0) |
161 (unpremultiply_alpha ? (1 << 1) : 0);
163 switch (target) {
164 case GL_TEXTURE_2D:
165 return shader_ids[index][SAMPLER_2D];
166 case GL_TEXTURE_RECTANGLE_ARB:
167 return shader_ids[index][SAMPLER_RECTANGLE_ARB];
168 case GL_TEXTURE_EXTERNAL_OES:
169 return shader_ids[index][SAMPLER_EXTERNAL_OES];
170 default:
171 break;
174 NOTREACHED();
175 return shader_ids[0][SAMPLER_2D];
178 void CompileShader(GLuint shader, const char* shader_source) {
179 glShaderSource(shader, 1, &shader_source, 0);
180 glCompileShader(shader);
181 #ifndef NDEBUG
182 GLint compile_status;
183 glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
184 if (GL_TRUE != compile_status)
185 DLOG(ERROR) << "CopyTextureCHROMIUM: shader compilation failure.";
186 #endif
189 void DeleteShader(GLuint shader) {
190 if (shader)
191 glDeleteShader(shader);
194 bool BindFramebufferTexture2D(GLenum target,
195 GLuint texture_id,
196 GLuint framebuffer) {
197 DCHECK(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB);
198 glActiveTexture(GL_TEXTURE0);
199 glBindTexture(target, texture_id);
200 // NVidia drivers require texture settings to be a certain way
201 // or they won't report FRAMEBUFFER_COMPLETE.
202 glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
203 glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
204 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
205 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
206 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
207 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target,
208 texture_id, 0);
210 #ifndef NDEBUG
211 GLenum fb_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
212 if (GL_FRAMEBUFFER_COMPLETE != fb_status) {
213 DLOG(ERROR) << "CopyTextureCHROMIUM: Incomplete framebuffer.";
214 return false;
216 #endif
217 return true;
220 void DoCopyTexImage2D(const gpu::gles2::GLES2Decoder* decoder,
221 GLenum source_target,
222 GLuint source_id,
223 GLuint dest_id,
224 GLenum dest_internal_format,
225 GLsizei width,
226 GLsizei height,
227 GLuint framebuffer) {
228 DCHECK(source_target == GL_TEXTURE_2D ||
229 source_target == GL_TEXTURE_RECTANGLE_ARB);
230 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) {
231 glBindTexture(GL_TEXTURE_2D, dest_id);
232 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
233 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
236 glCopyTexImage2D(GL_TEXTURE_2D, 0 /* level */, dest_internal_format,
237 0 /* x */, 0 /* y */, width, height, 0 /* border */);
240 decoder->RestoreTextureState(source_id);
241 decoder->RestoreTextureState(dest_id);
242 decoder->RestoreTextureUnitBindings(0);
243 decoder->RestoreActiveTexture();
244 decoder->RestoreFramebufferBindings();
247 void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder,
248 GLenum source_target,
249 GLuint source_id,
250 GLuint dest_id,
251 GLint xoffset,
252 GLint yoffset,
253 GLsizei source_width,
254 GLsizei source_height,
255 GLuint framebuffer) {
256 DCHECK(source_target == GL_TEXTURE_2D ||
257 source_target == GL_TEXTURE_RECTANGLE_ARB);
258 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) {
259 glBindTexture(GL_TEXTURE_2D, dest_id);
260 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
261 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
262 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
263 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
264 glCopyTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, xoffset, yoffset,
265 0 /* x */, 0 /* y */, source_width, source_height);
268 decoder->RestoreTextureState(source_id);
269 decoder->RestoreTextureState(dest_id);
270 decoder->RestoreTextureUnitBindings(0);
271 decoder->RestoreActiveTexture();
272 decoder->RestoreFramebufferBindings();
275 // Copy from SkMatrix44::preTranslate
276 void PreTranslate(GLfloat* matrix, GLfloat dx, GLfloat dy, GLfloat dz) {
277 if (!dx && !dy && !dz)
278 return;
280 for (int i = 0; i < 4; ++i) {
281 matrix[(3 * 4) + i] = matrix[(0 * 4) + i] * dx + matrix[(1 * 4) + i] * dy +
282 matrix[(2 * 4) + i] * dz + matrix[(3 * 4) + i];
286 } // namespace
288 namespace gpu {
290 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager()
291 : initialized_(false),
292 vertex_shaders_(NUM_VERTEX_SHADERS, 0u),
293 fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u),
294 buffer_id_(0u),
295 framebuffer_(0u) {}
297 CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() {
298 // |buffer_id_| and |framebuffer_| can be not-null because when GPU context is
299 // lost, this class can be deleted without releasing resources like
300 // GLES2DecoderImpl.
303 void CopyTextureCHROMIUMResourceManager::Initialize(
304 const gles2::GLES2Decoder* decoder) {
305 static_assert(
306 kVertexPositionAttrib == 0u,
307 "kVertexPositionAttrib must be 0");
308 DCHECK(!buffer_id_);
309 DCHECK(!framebuffer_);
310 DCHECK(programs_.empty());
312 // Initialize all of the GPU resources required to perform the copy.
313 glGenBuffersARB(1, &buffer_id_);
314 glBindBuffer(GL_ARRAY_BUFFER, buffer_id_);
315 const GLfloat kQuadVertices[] = {-1.0f, -1.0f,
316 1.0f, -1.0f,
317 1.0f, 1.0f,
318 -1.0f, 1.0f};
319 glBufferData(
320 GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, GL_STATIC_DRAW);
322 glGenFramebuffersEXT(1, &framebuffer_);
324 decoder->RestoreBufferBindings();
326 initialized_ = true;
329 void CopyTextureCHROMIUMResourceManager::Destroy() {
330 if (!initialized_)
331 return;
333 glDeleteFramebuffersEXT(1, &framebuffer_);
334 framebuffer_ = 0;
336 std::for_each(vertex_shaders_.begin(), vertex_shaders_.end(), DeleteShader);
337 std::for_each(
338 fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader);
340 for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end();
341 ++it) {
342 const ProgramInfo& info = it->second;
343 glDeleteProgram(info.program);
346 glDeleteBuffersARB(1, &buffer_id_);
347 buffer_id_ = 0;
350 void CopyTextureCHROMIUMResourceManager::DoCopyTexture(
351 const gles2::GLES2Decoder* decoder,
352 GLenum source_target,
353 GLuint source_id,
354 GLenum source_internal_format,
355 GLuint dest_id,
356 GLenum dest_internal_format,
357 GLsizei width,
358 GLsizei height,
359 bool flip_y,
360 bool premultiply_alpha,
361 bool unpremultiply_alpha) {
362 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha;
363 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's
364 // format does not contain a superset of the components required by the base
365 // format of internalformat.
366 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml
367 bool source_format_contain_superset_of_dest_format =
368 (source_internal_format == dest_internal_format &&
369 source_internal_format != GL_BGRA_EXT) ||
370 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB);
371 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2,
372 // so restrict this to GL_TEXTURE_2D.
373 if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change &&
374 source_format_contain_superset_of_dest_format) {
375 DoCopyTexImage2D(decoder,
376 source_target,
377 source_id,
378 dest_id,
379 dest_internal_format,
380 width,
381 height,
382 framebuffer_);
383 return;
386 // Use kIdentityMatrix if no transform passed in.
387 DoCopyTextureWithTransform(decoder, source_target, source_id, dest_id, width,
388 height, flip_y, premultiply_alpha,
389 unpremultiply_alpha, kIdentityMatrix);
392 void CopyTextureCHROMIUMResourceManager::DoCopySubTexture(
393 const gles2::GLES2Decoder* decoder,
394 GLenum source_target,
395 GLuint source_id,
396 GLenum source_internal_format,
397 GLuint dest_id,
398 GLenum dest_internal_format,
399 GLint xoffset,
400 GLint yoffset,
401 GLsizei dest_width,
402 GLsizei dest_height,
403 GLsizei source_width,
404 GLsizei source_height,
405 bool flip_y,
406 bool premultiply_alpha,
407 bool unpremultiply_alpha) {
408 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha;
409 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's
410 // format does not contain a superset of the components required by the base
411 // format of internalformat.
412 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml
413 bool source_format_contain_superset_of_dest_format =
414 (source_internal_format == dest_internal_format &&
415 source_internal_format != GL_BGRA_EXT) ||
416 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB);
417 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2,
418 // so restrict this to GL_TEXTURE_2D.
419 if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change &&
420 source_format_contain_superset_of_dest_format) {
421 DoCopyTexSubImage2D(decoder, source_target, source_id, dest_id, xoffset,
422 yoffset, source_width, source_height, framebuffer_);
423 return;
426 // Use kIdentityMatrix if no transform passed in.
427 DoCopySubTextureWithTransform(
428 decoder, source_target, source_id, dest_id, xoffset, yoffset, dest_width,
429 dest_height, source_width, source_height, flip_y, premultiply_alpha,
430 unpremultiply_alpha, kIdentityMatrix);
433 void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
434 const gles2::GLES2Decoder* decoder,
435 GLenum source_target,
436 GLuint source_id,
437 GLuint dest_id,
438 GLsizei width,
439 GLsizei height,
440 bool flip_y,
441 bool premultiply_alpha,
442 bool unpremultiply_alpha,
443 const GLfloat transform_matrix[16]) {
444 GLsizei dest_width = width;
445 GLsizei dest_height = height;
446 DoCopyTextureInternal(decoder, source_target, source_id, dest_id, 0, 0,
447 dest_width, dest_height, width, height, flip_y,
448 premultiply_alpha, unpremultiply_alpha,
449 transform_matrix);
452 void CopyTextureCHROMIUMResourceManager::DoCopySubTextureWithTransform(
453 const gles2::GLES2Decoder* decoder,
454 GLenum source_target,
455 GLuint source_id,
456 GLuint dest_id,
457 GLint xoffset,
458 GLint yoffset,
459 GLsizei dest_width,
460 GLsizei dest_height,
461 GLsizei source_width,
462 GLsizei source_height,
463 bool flip_y,
464 bool premultiply_alpha,
465 bool unpremultiply_alpha,
466 const GLfloat transform_matrix[16]) {
467 DoCopyTextureInternal(decoder, source_target, source_id, dest_id, xoffset,
468 yoffset, dest_width, dest_height, source_width,
469 source_height, flip_y, premultiply_alpha,
470 unpremultiply_alpha, transform_matrix);
473 void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal(
474 const gles2::GLES2Decoder* decoder,
475 GLenum source_target,
476 GLuint source_id,
477 GLuint dest_id,
478 GLint xoffset,
479 GLint yoffset,
480 GLsizei dest_width,
481 GLsizei dest_height,
482 GLsizei source_width,
483 GLsizei source_height,
484 bool flip_y,
485 bool premultiply_alpha,
486 bool unpremultiply_alpha,
487 const GLfloat transform_matrix[16]) {
488 DCHECK(source_target == GL_TEXTURE_2D ||
489 source_target == GL_TEXTURE_RECTANGLE_ARB ||
490 source_target == GL_TEXTURE_EXTERNAL_OES);
491 DCHECK(xoffset >= 0 && xoffset + source_width <= dest_width);
492 DCHECK(yoffset >= 0 && yoffset + source_height <= dest_height);
493 if (!initialized_) {
494 DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager.";
495 return;
498 VertexShaderId vertex_shader_id = GetVertexShaderId(flip_y);
499 DCHECK_LT(static_cast<size_t>(vertex_shader_id), vertex_shaders_.size());
500 FragmentShaderId fragment_shader_id = GetFragmentShaderId(
501 premultiply_alpha, unpremultiply_alpha, source_target);
502 DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size());
504 ProgramMapKey key(vertex_shader_id, fragment_shader_id);
505 ProgramInfo* info = &programs_[key];
506 // Create program if necessary.
507 if (!info->program) {
508 info->program = glCreateProgram();
509 GLuint* vertex_shader = &vertex_shaders_[vertex_shader_id];
510 if (!*vertex_shader) {
511 *vertex_shader = glCreateShader(GL_VERTEX_SHADER);
512 CompileShader(*vertex_shader, vertex_shader_source[vertex_shader_id]);
514 glAttachShader(info->program, *vertex_shader);
515 GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id];
516 if (!*fragment_shader) {
517 *fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
518 CompileShader(*fragment_shader,
519 fragment_shader_source[fragment_shader_id]);
521 glAttachShader(info->program, *fragment_shader);
522 glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position");
523 glLinkProgram(info->program);
524 #ifndef NDEBUG
525 GLint linked;
526 glGetProgramiv(info->program, GL_LINK_STATUS, &linked);
527 if (!linked)
528 DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure.";
529 #endif
530 info->matrix_handle = glGetUniformLocation(info->program, "u_matrix");
531 info->half_size_handle = glGetUniformLocation(info->program, "u_half_size");
532 info->sampler_handle = glGetUniformLocation(info->program, "u_sampler");
534 glUseProgram(info->program);
536 if (!xoffset && !yoffset) {
537 glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, transform_matrix);
538 } else {
539 // transform offsets from ([0, dest_width], [0, dest_height]) coord.
540 // to ([-1, 1], [-1, 1]) coord.
541 GLfloat xoffset_on_vertex = ((2.f * xoffset) / dest_width);
542 GLfloat yoffset_on_vertex = ((2.f * yoffset) / dest_height);
544 // Pass view_matrix * offset_matrix to the program.
545 GLfloat view_transform[16];
546 memcpy(view_transform, transform_matrix, 16 * sizeof(GLfloat));
547 PreTranslate(view_transform, xoffset_on_vertex, yoffset_on_vertex, 0);
548 glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, view_transform);
550 if (source_target == GL_TEXTURE_RECTANGLE_ARB)
551 glUniform2f(info->half_size_handle, source_width / 2.0f,
552 source_height / 2.0f);
553 else
554 glUniform2f(info->half_size_handle, 0.5f, 0.5f);
556 if (BindFramebufferTexture2D(GL_TEXTURE_2D, dest_id, framebuffer_)) {
557 #ifndef NDEBUG
558 // glValidateProgram of MACOSX validates FBO unlike other platforms, so
559 // glValidateProgram must be called after FBO binding. crbug.com/463439
560 glValidateProgram(info->program);
561 GLint validation_status;
562 glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status);
563 if (GL_TRUE != validation_status) {
564 DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader.";
565 return;
567 #endif
568 decoder->ClearAllAttributes();
569 glEnableVertexAttribArray(kVertexPositionAttrib);
571 glBindBuffer(GL_ARRAY_BUFFER, buffer_id_);
572 glVertexAttribPointer(kVertexPositionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
574 glUniform1i(info->sampler_handle, 0);
576 glBindTexture(source_target, source_id);
577 glTexParameterf(source_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
578 glTexParameterf(source_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
579 glTexParameteri(source_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
580 glTexParameteri(source_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
582 glDisable(GL_DEPTH_TEST);
583 glDisable(GL_SCISSOR_TEST);
584 glDisable(GL_STENCIL_TEST);
585 glDisable(GL_CULL_FACE);
586 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
587 glDepthMask(GL_FALSE);
588 glDisable(GL_BLEND);
590 glViewport(0, 0, dest_width, dest_height);
591 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
594 decoder->RestoreAllAttributes();
595 decoder->RestoreTextureState(source_id);
596 decoder->RestoreTextureState(dest_id);
597 decoder->RestoreTextureUnitBindings(0);
598 decoder->RestoreActiveTexture();
599 decoder->RestoreProgramBindings();
600 decoder->RestoreBufferBindings();
601 decoder->RestoreFramebufferBindings();
602 decoder->RestoreGlobalState();
605 } // namespace gpu