Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / gpu / command_buffer / service / gles2_cmd_copy_texture_chromium.cc
blob846ac0d6a12b9be9218a3d26a2a866fc87c67292
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 vec2 u_vertex_translate;
63 uniform vec2 u_half_size;
64 attribute vec4 a_position;
65 varying TexCoordPrecision vec2 v_uv;
66 void main(void) {
67 gl_Position = a_position + vec4(u_vertex_translate, 0.0, 0.0);
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 vec2 u_vertex_translate;
74 uniform vec2 u_half_size;
75 attribute vec4 a_position;
76 varying TexCoordPrecision vec2 v_uv;
77 void main(void) {
78 gl_Position = a_position + vec4(u_vertex_translate, 0.0, 0.0);
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 uniform mat4 u_tex_coord_transform;
89 varying TexCoordPrecision vec2 v_uv;
90 void main(void) {
91 TexCoordPrecision vec4 uv = u_tex_coord_transform * vec4(v_uv, 0, 1);
92 gl_FragColor = TextureLookup(u_sampler, uv.st);
93 }),
94 // FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_*
95 FRAGMENT_SHADERS(
96 uniform SamplerType u_sampler;
97 uniform mat4 u_tex_coord_transform;
98 varying TexCoordPrecision vec2 v_uv;
99 void main(void) {
100 TexCoordPrecision vec4 uv = u_tex_coord_transform * vec4(v_uv, 0, 1);
101 gl_FragColor = TextureLookup(u_sampler, uv.st);
102 gl_FragColor.rgb *= gl_FragColor.a;
104 // FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_*
105 FRAGMENT_SHADERS(
106 uniform SamplerType u_sampler;
107 uniform mat4 u_tex_coord_transform;
108 varying TexCoordPrecision vec2 v_uv;
109 void main(void) {
110 TexCoordPrecision vec4 uv = u_tex_coord_transform * vec4(v_uv, 0, 1);
111 gl_FragColor = TextureLookup(u_sampler, uv.st);
112 if (gl_FragColor.a > 0.0)
113 gl_FragColor.rgb /= gl_FragColor.a;
117 // Returns the correct vertex shader id to evaluate the copy operation for
118 // the CHROMIUM_flipy setting.
119 VertexShaderId GetVertexShaderId(bool flip_y) {
120 // bit 0: flip y
121 static VertexShaderId shader_ids[] = {
122 VERTEX_SHADER_COPY_TEXTURE,
123 VERTEX_SHADER_COPY_TEXTURE_FLIP_Y,
126 unsigned index = flip_y ? 1 : 0;
127 return shader_ids[index];
130 // Returns the correct fragment shader id to evaluate the copy operation for
131 // the premultiply alpha pixel store settings and target.
132 FragmentShaderId GetFragmentShaderId(bool premultiply_alpha,
133 bool unpremultiply_alpha,
134 GLenum target) {
135 enum {
136 SAMPLER_2D,
137 SAMPLER_RECTANGLE_ARB,
138 SAMPLER_EXTERNAL_OES,
139 NUM_SAMPLERS
142 // bit 0: premultiply alpha
143 // bit 1: unpremultiply alpha
144 static FragmentShaderId shader_ids[][NUM_SAMPLERS] = {
146 FRAGMENT_SHADER_COPY_TEXTURE_2D,
147 FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB,
148 FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES,
151 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D,
152 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_RECTANGLE_ARB,
153 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES,
156 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D,
157 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_RECTANGLE_ARB,
158 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES,
161 FRAGMENT_SHADER_COPY_TEXTURE_2D,
162 FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB,
163 FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES,
166 unsigned index = (premultiply_alpha ? (1 << 0) : 0) |
167 (unpremultiply_alpha ? (1 << 1) : 0);
169 switch (target) {
170 case GL_TEXTURE_2D:
171 return shader_ids[index][SAMPLER_2D];
172 case GL_TEXTURE_RECTANGLE_ARB:
173 return shader_ids[index][SAMPLER_RECTANGLE_ARB];
174 case GL_TEXTURE_EXTERNAL_OES:
175 return shader_ids[index][SAMPLER_EXTERNAL_OES];
176 default:
177 break;
180 NOTREACHED();
181 return shader_ids[0][SAMPLER_2D];
184 void CompileShader(GLuint shader, const char* shader_source) {
185 glShaderSource(shader, 1, &shader_source, 0);
186 glCompileShader(shader);
187 #ifndef NDEBUG
188 GLint compile_status;
189 glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
190 if (GL_TRUE != compile_status)
191 DLOG(ERROR) << "CopyTextureCHROMIUM: shader compilation failure.";
192 #endif
195 void DeleteShader(GLuint shader) {
196 if (shader)
197 glDeleteShader(shader);
200 bool BindFramebufferTexture2D(GLenum target,
201 GLuint texture_id,
202 GLuint framebuffer) {
203 DCHECK(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB);
204 glActiveTexture(GL_TEXTURE0);
205 glBindTexture(target, texture_id);
206 // NVidia drivers require texture settings to be a certain way
207 // or they won't report FRAMEBUFFER_COMPLETE.
208 glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
209 glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
210 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
211 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
212 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
213 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target,
214 texture_id, 0);
216 #ifndef NDEBUG
217 GLenum fb_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
218 if (GL_FRAMEBUFFER_COMPLETE != fb_status) {
219 DLOG(ERROR) << "CopyTextureCHROMIUM: Incomplete framebuffer.";
220 return false;
222 #endif
223 return true;
226 void DoCopyTexImage2D(const gpu::gles2::GLES2Decoder* decoder,
227 GLenum source_target,
228 GLuint source_id,
229 GLuint dest_id,
230 GLenum dest_internal_format,
231 GLsizei width,
232 GLsizei height,
233 GLuint framebuffer) {
234 DCHECK(source_target == GL_TEXTURE_2D ||
235 source_target == GL_TEXTURE_RECTANGLE_ARB);
236 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) {
237 glBindTexture(GL_TEXTURE_2D, dest_id);
238 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
239 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
240 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
242 glCopyTexImage2D(GL_TEXTURE_2D, 0 /* level */, dest_internal_format,
243 0 /* x */, 0 /* y */, width, height, 0 /* border */);
246 decoder->RestoreTextureState(source_id);
247 decoder->RestoreTextureState(dest_id);
248 decoder->RestoreTextureUnitBindings(0);
249 decoder->RestoreActiveTexture();
250 decoder->RestoreFramebufferBindings();
253 void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder,
254 GLenum source_target,
255 GLuint source_id,
256 GLuint dest_id,
257 GLint xoffset,
258 GLint yoffset,
259 GLint source_x,
260 GLint source_y,
261 GLsizei source_width,
262 GLsizei source_height,
263 GLuint framebuffer) {
264 DCHECK(source_target == GL_TEXTURE_2D ||
265 source_target == GL_TEXTURE_RECTANGLE_ARB);
266 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) {
267 glBindTexture(GL_TEXTURE_2D, dest_id);
268 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
269 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
270 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
271 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
272 glCopyTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, xoffset, yoffset,
273 source_x, source_y, source_width, source_height);
276 decoder->RestoreTextureState(source_id);
277 decoder->RestoreTextureState(dest_id);
278 decoder->RestoreTextureUnitBindings(0);
279 decoder->RestoreActiveTexture();
280 decoder->RestoreFramebufferBindings();
283 } // namespace
285 namespace gpu {
287 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager()
288 : initialized_(false),
289 vertex_shaders_(NUM_VERTEX_SHADERS, 0u),
290 fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u),
291 buffer_id_(0u),
292 framebuffer_(0u) {}
294 CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() {
295 // |buffer_id_| and |framebuffer_| can be not-null because when GPU context is
296 // lost, this class can be deleted without releasing resources like
297 // GLES2DecoderImpl.
300 void CopyTextureCHROMIUMResourceManager::Initialize(
301 const gles2::GLES2Decoder* decoder) {
302 static_assert(
303 kVertexPositionAttrib == 0u,
304 "kVertexPositionAttrib must be 0");
305 DCHECK(!buffer_id_);
306 DCHECK(!framebuffer_);
307 DCHECK(programs_.empty());
309 // Initialize all of the GPU resources required to perform the copy.
310 glGenBuffersARB(1, &buffer_id_);
311 glBindBuffer(GL_ARRAY_BUFFER, buffer_id_);
312 const GLfloat kQuadVertices[] = {-1.0f, -1.0f,
313 1.0f, -1.0f,
314 1.0f, 1.0f,
315 -1.0f, 1.0f};
316 glBufferData(
317 GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, GL_STATIC_DRAW);
319 glGenFramebuffersEXT(1, &framebuffer_);
321 decoder->RestoreBufferBindings();
323 initialized_ = true;
326 void CopyTextureCHROMIUMResourceManager::Destroy() {
327 if (!initialized_)
328 return;
330 glDeleteFramebuffersEXT(1, &framebuffer_);
331 framebuffer_ = 0;
333 std::for_each(vertex_shaders_.begin(), vertex_shaders_.end(), DeleteShader);
334 std::for_each(
335 fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader);
337 for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end();
338 ++it) {
339 const ProgramInfo& info = it->second;
340 glDeleteProgram(info.program);
343 glDeleteBuffersARB(1, &buffer_id_);
344 buffer_id_ = 0;
347 void CopyTextureCHROMIUMResourceManager::DoCopyTexture(
348 const gles2::GLES2Decoder* decoder,
349 GLenum source_target,
350 GLuint source_id,
351 GLenum source_internal_format,
352 GLuint dest_id,
353 GLenum dest_internal_format,
354 GLsizei width,
355 GLsizei height,
356 bool flip_y,
357 bool premultiply_alpha,
358 bool unpremultiply_alpha) {
359 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha;
360 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's
361 // format does not contain a superset of the components required by the base
362 // format of internalformat.
363 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml
364 bool source_format_contain_superset_of_dest_format =
365 (source_internal_format == dest_internal_format &&
366 source_internal_format != GL_BGRA_EXT) ||
367 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB);
368 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2,
369 // so restrict this to GL_TEXTURE_2D.
370 if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change &&
371 source_format_contain_superset_of_dest_format) {
372 DoCopyTexImage2D(decoder,
373 source_target,
374 source_id,
375 dest_id,
376 dest_internal_format,
377 width,
378 height,
379 framebuffer_);
380 return;
383 // Use kIdentityMatrix if no transform passed in.
384 DoCopyTextureWithTransform(decoder, source_target, source_id, dest_id, width,
385 height, flip_y, premultiply_alpha,
386 unpremultiply_alpha, kIdentityMatrix);
389 void CopyTextureCHROMIUMResourceManager::DoCopySubTexture(
390 const gles2::GLES2Decoder* decoder,
391 GLenum source_target,
392 GLuint source_id,
393 GLenum source_internal_format,
394 GLuint dest_id,
395 GLenum dest_internal_format,
396 GLint xoffset,
397 GLint yoffset,
398 GLint x,
399 GLint y,
400 GLsizei width,
401 GLsizei height,
402 GLsizei dest_width,
403 GLsizei dest_height,
404 GLsizei source_width,
405 GLsizei source_height,
406 bool flip_y,
407 bool premultiply_alpha,
408 bool unpremultiply_alpha) {
409 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha;
410 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's
411 // format does not contain a superset of the components required by the base
412 // format of internalformat.
413 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml
414 bool source_format_contain_superset_of_dest_format =
415 (source_internal_format == dest_internal_format &&
416 source_internal_format != GL_BGRA_EXT) ||
417 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB);
418 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2,
419 // so restrict this to GL_TEXTURE_2D.
420 if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change &&
421 source_format_contain_superset_of_dest_format) {
422 DoCopyTexSubImage2D(decoder, source_target, source_id, dest_id, xoffset,
423 yoffset, x, y, width, height, framebuffer_);
424 return;
427 DoCopyTextureInternal(decoder, source_target, source_id, dest_id, xoffset,
428 yoffset, x, y, width, height, dest_width, dest_height,
429 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, 0, 0,
447 width, height, dest_width, dest_height, width, height,
448 flip_y, premultiply_alpha, unpremultiply_alpha,
449 transform_matrix);
452 void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal(
453 const gles2::GLES2Decoder* decoder,
454 GLenum source_target,
455 GLuint source_id,
456 GLuint dest_id,
457 GLint xoffset,
458 GLint yoffset,
459 GLint x,
460 GLint y,
461 GLsizei width,
462 GLsizei height,
463 GLsizei dest_width,
464 GLsizei dest_height,
465 GLsizei source_width,
466 GLsizei source_height,
467 bool flip_y,
468 bool premultiply_alpha,
469 bool unpremultiply_alpha,
470 const GLfloat transform_matrix[16]) {
471 DCHECK(source_target == GL_TEXTURE_2D ||
472 source_target == GL_TEXTURE_RECTANGLE_ARB ||
473 source_target == GL_TEXTURE_EXTERNAL_OES);
474 DCHECK(xoffset >= 0 && xoffset + source_width <= dest_width);
475 DCHECK(yoffset >= 0 && yoffset + source_height <= dest_height);
476 if (!initialized_) {
477 DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager.";
478 return;
481 VertexShaderId vertex_shader_id = GetVertexShaderId(flip_y);
482 DCHECK_LT(static_cast<size_t>(vertex_shader_id), vertex_shaders_.size());
483 FragmentShaderId fragment_shader_id = GetFragmentShaderId(
484 premultiply_alpha, unpremultiply_alpha, source_target);
485 DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size());
487 ProgramMapKey key(vertex_shader_id, fragment_shader_id);
488 ProgramInfo* info = &programs_[key];
489 // Create program if necessary.
490 if (!info->program) {
491 info->program = glCreateProgram();
492 GLuint* vertex_shader = &vertex_shaders_[vertex_shader_id];
493 if (!*vertex_shader) {
494 *vertex_shader = glCreateShader(GL_VERTEX_SHADER);
495 CompileShader(*vertex_shader, vertex_shader_source[vertex_shader_id]);
497 glAttachShader(info->program, *vertex_shader);
498 GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id];
499 if (!*fragment_shader) {
500 *fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
501 CompileShader(*fragment_shader,
502 fragment_shader_source[fragment_shader_id]);
504 glAttachShader(info->program, *fragment_shader);
505 glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position");
506 glLinkProgram(info->program);
507 #ifndef NDEBUG
508 GLint linked;
509 glGetProgramiv(info->program, GL_LINK_STATUS, &linked);
510 if (!linked)
511 DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure.";
512 #endif
513 info->vertex_translate_handle = glGetUniformLocation(info->program,
514 "u_vertex_translate");
515 info->tex_coord_transform_handle =
516 glGetUniformLocation(info->program, "u_tex_coord_transform");
517 info->half_size_handle = glGetUniformLocation(info->program, "u_half_size");
518 info->sampler_handle = glGetUniformLocation(info->program, "u_sampler");
520 glUseProgram(info->program);
522 glUniformMatrix4fv(info->tex_coord_transform_handle, 1, GL_FALSE,
523 transform_matrix);
525 GLint x_translate = xoffset - x;
526 GLint y_translate = yoffset - y;
527 if (!x_translate && !y_translate) {
528 glUniform2f(info->vertex_translate_handle, 0.0f, 0.0f);
529 } else {
530 // transform offsets from ([0, dest_width], [0, dest_height]) coord.
531 // to ([-1, 1], [-1, 1]) coord.
532 GLfloat x_translate_on_vertex = ((2.f * x_translate) / dest_width);
533 GLfloat y_translate_on_vertex = ((2.f * y_translate) / dest_height);
535 // Pass translation to the shader program.
536 glUniform2f(info->vertex_translate_handle, x_translate_on_vertex,
537 y_translate_on_vertex);
539 if (source_target == GL_TEXTURE_RECTANGLE_ARB)
540 glUniform2f(info->half_size_handle, source_width / 2.0f,
541 source_height / 2.0f);
542 else
543 glUniform2f(info->half_size_handle, 0.5f, 0.5f);
545 if (BindFramebufferTexture2D(GL_TEXTURE_2D, dest_id, framebuffer_)) {
546 #ifndef NDEBUG
547 // glValidateProgram of MACOSX validates FBO unlike other platforms, so
548 // glValidateProgram must be called after FBO binding. crbug.com/463439
549 glValidateProgram(info->program);
550 GLint validation_status;
551 glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status);
552 if (GL_TRUE != validation_status) {
553 DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader.";
554 return;
556 #endif
557 decoder->ClearAllAttributes();
558 glEnableVertexAttribArray(kVertexPositionAttrib);
560 glBindBuffer(GL_ARRAY_BUFFER, buffer_id_);
561 glVertexAttribPointer(kVertexPositionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
563 glUniform1i(info->sampler_handle, 0);
565 glBindTexture(source_target, source_id);
566 glTexParameterf(source_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
567 glTexParameterf(source_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
568 glTexParameteri(source_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
569 glTexParameteri(source_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
571 glDisable(GL_DEPTH_TEST);
572 glDisable(GL_STENCIL_TEST);
573 glDisable(GL_CULL_FACE);
574 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
575 glDepthMask(GL_FALSE);
576 glDisable(GL_BLEND);
578 bool need_scissor =
579 xoffset || yoffset || width != dest_width || height != dest_height;
580 if (need_scissor) {
581 glEnable(GL_SCISSOR_TEST);
582 glScissor(xoffset, yoffset, width, height);
584 glViewport(0, 0, dest_width, dest_height);
585 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
588 decoder->RestoreAllAttributes();
589 decoder->RestoreTextureState(source_id);
590 decoder->RestoreTextureState(dest_id);
591 decoder->RestoreTextureUnitBindings(0);
592 decoder->RestoreActiveTexture();
593 decoder->RestoreProgramBindings();
594 decoder->RestoreBufferBindings();
595 decoder->RestoreFramebufferBindings();
596 decoder->RestoreGlobalState();
599 } // namespace gpu