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

Side by Side Diff: gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc

Issue 1547873002: Allow GL_TEXTURE_RECTANGLE_ARB to be the destination target for copyTextureCHROMIUM. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments from kbr. Created 4 years, 11 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" 5 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 10
11 #include "gpu/command_buffer/service/gl_utils.h" 11 #include "gpu/command_buffer/service/gl_utils.h"
12 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" 12 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
13 #include "ui/gl/gl_implementation.h" 13 #include "ui/gl/gl_implementation.h"
14 14
15 namespace { 15 namespace {
16 16
17 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 17 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
18 0.0f, 1.0f, 0.0f, 0.0f, 18 0.0f, 1.0f, 0.0f, 0.0f,
19 0.0f, 0.0f, 1.0f, 0.0f, 19 0.0f, 0.0f, 1.0f, 0.0f,
20 0.0f, 0.0f, 0.0f, 1.0f}; 20 0.0f, 0.0f, 0.0f, 1.0f};
21 21
22 enum VertexShaderId {
23 VERTEX_SHADER_COPY_TEXTURE,
24 VERTEX_SHADER_COPY_TEXTURE_FLIP_Y,
25 NUM_VERTEX_SHADERS,
26 };
27
28 enum FragmentShaderId { 22 enum FragmentShaderId {
29 FRAGMENT_SHADER_COPY_TEXTURE_2D, 23 FRAGMENT_SHADER_COPY_TEXTURE_2D,
30 FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB, 24 FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB,
31 FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES, 25 FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES,
32 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D, 26 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D,
33 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_RECTANGLE_ARB, 27 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_RECTANGLE_ARB,
34 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES, 28 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES,
35 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D, 29 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D,
36 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_RECTANGLE_ARB, 30 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_RECTANGLE_ARB,
37 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES, 31 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES,
38 NUM_FRAGMENT_SHADERS, 32 NUM_FRAGMENT_SHADERS,
39 }; 33 };
40 34
41 // Returns the correct vertex shader id to evaluate the copy operation for
42 // the CHROMIUM_flipy setting.
43 VertexShaderId GetVertexShaderId(bool flip_y) {
44 // bit 0: flip y
45 static VertexShaderId shader_ids[] = {
46 VERTEX_SHADER_COPY_TEXTURE,
47 VERTEX_SHADER_COPY_TEXTURE_FLIP_Y,
48 };
49
50 unsigned index = flip_y ? 1 : 0;
51 return shader_ids[index];
52 }
53
54 // Returns the correct fragment shader id to evaluate the copy operation for 35 // Returns the correct fragment shader id to evaluate the copy operation for
55 // the premultiply alpha pixel store settings and target. 36 // the premultiply alpha pixel store settings and target.
56 FragmentShaderId GetFragmentShaderId(bool premultiply_alpha, 37 FragmentShaderId GetFragmentShaderId(bool premultiply_alpha,
57 bool unpremultiply_alpha, 38 bool unpremultiply_alpha,
58 GLenum target) { 39 GLenum target) {
59 // Only one alpha mode at a time makes sense. 40 // Only one alpha mode at a time makes sense.
60 DCHECK(!premultiply_alpha || !unpremultiply_alpha); 41 DCHECK(!premultiply_alpha || !unpremultiply_alpha);
61 42
62 enum { 43 enum {
63 SAMPLER_2D, 44 SAMPLER_2D,
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 } 90 }
110 91
111 const char* kShaderPrecisionPreamble = "\ 92 const char* kShaderPrecisionPreamble = "\
112 #ifdef GL_ES\n\ 93 #ifdef GL_ES\n\
113 precision mediump float;\n\ 94 precision mediump float;\n\
114 #define TexCoordPrecision mediump\n\ 95 #define TexCoordPrecision mediump\n\
115 #else\n\ 96 #else\n\
116 #define TexCoordPrecision\n\ 97 #define TexCoordPrecision\n\
117 #endif\n"; 98 #endif\n";
118 99
119 std::string GetVertexShaderSource(bool flip_y) { 100 std::string GetVertexShaderSource() {
120 std::string source; 101 std::string source;
121 102
122 // Preamble for core and compatibility mode. 103 // Preamble for core and compatibility mode.
123 if (gfx::GetGLImplementation() == 104 if (gfx::GetGLImplementation() ==
124 gfx::kGLImplementationDesktopGLCoreProfile) { 105 gfx::kGLImplementationDesktopGLCoreProfile) {
125 source += std::string("\ 106 source += std::string("\
126 #version 150\n\ 107 #version 150\n\
127 #define ATTRIBUTE in\n\ 108 #define ATTRIBUTE in\n\
128 #define VARYING out\n"); 109 #define VARYING out\n");
129 } else { 110 } else {
130 source += std::string("\ 111 source += std::string("\
131 #define ATTRIBUTE attribute\n\ 112 #define ATTRIBUTE attribute\n\
132 #define VARYING varying\n"); 113 #define VARYING varying\n");
133 } 114 }
134 115
135 // Preamble for texture precision. 116 // Preamble for texture precision.
136 source += std::string(kShaderPrecisionPreamble); 117 source += std::string(kShaderPrecisionPreamble);
137 118
138 // Preamble to differentiate based on |flip_y|.
139 if (flip_y) {
140 source += std::string("#define SIGN -\n");
141 } else {
142 source += std::string("#define SIGN\n");
143 }
144
145 // Main shader source. 119 // Main shader source.
146 source += std::string("\ 120 source += std::string("\
147 uniform vec2 u_vertex_translate;\n\ 121 uniform vec2 u_vertex_dest_mult;\n\
148 uniform vec2 u_half_size;\n\ 122 uniform vec2 u_vertex_dest_add;\n\
123 uniform vec2 u_vertex_source_mult;\n\
124 uniform vec2 u_vertex_source_add;\n\
149 ATTRIBUTE vec4 a_position;\n\ 125 ATTRIBUTE vec4 a_position;\n\
150 VARYING TexCoordPrecision vec2 v_uv;\n\ 126 VARYING TexCoordPrecision vec2 v_uv;\n\
151 void main(void) {\n\ 127 void main(void) {\n\
152 gl_Position = a_position + vec4(u_vertex_translate, 0.0, 0.0);\n\ 128 gl_Position = a_position;\n\
153 v_uv = a_position.xy * vec2(u_half_size.s, SIGN u_half_size.t) +\n\ 129 gl_Position.xy = a_position.xy * u_vertex_dest_mult + \
154 vec2(u_half_size.s, u_half_size.t);\n\ 130 u_vertex_dest_add;\n\
131 v_uv = a_position.xy * u_vertex_source_mult + u_vertex_source_add;\n\
155 }\n"); 132 }\n");
156 133
157 return source; 134 return source;
158 } 135 }
159 136
160 std::string GetFragmentShaderSource(bool premultiply_alpha, 137 std::string GetFragmentShaderSource(bool premultiply_alpha,
161 bool unpremultiply_alpha, 138 bool unpremultiply_alpha,
162 GLenum target) { 139 GLenum target) {
163 // Only one alpha mode at a time makes sense. 140 // Only one alpha mode at a time makes sense.
164 DCHECK(!premultiply_alpha || !unpremultiply_alpha); 141 DCHECK(!premultiply_alpha || !unpremultiply_alpha);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 DLOG(ERROR) << "CopyTextureCHROMIUM: Incomplete framebuffer."; 255 DLOG(ERROR) << "CopyTextureCHROMIUM: Incomplete framebuffer.";
279 return false; 256 return false;
280 } 257 }
281 #endif 258 #endif
282 return true; 259 return true;
283 } 260 }
284 261
285 void DoCopyTexImage2D(const gpu::gles2::GLES2Decoder* decoder, 262 void DoCopyTexImage2D(const gpu::gles2::GLES2Decoder* decoder,
286 GLenum source_target, 263 GLenum source_target,
287 GLuint source_id, 264 GLuint source_id,
265 GLenum dest_target,
288 GLuint dest_id, 266 GLuint dest_id,
289 GLenum dest_internal_format, 267 GLenum dest_internal_format,
290 GLsizei width, 268 GLsizei width,
291 GLsizei height, 269 GLsizei height,
292 GLuint framebuffer) { 270 GLuint framebuffer) {
293 DCHECK(source_target == GL_TEXTURE_2D || 271 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), source_target);
294 source_target == GL_TEXTURE_RECTANGLE_ARB); 272 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), dest_target);
295 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { 273 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) {
296 glBindTexture(GL_TEXTURE_2D, dest_id); 274 glBindTexture(dest_target, dest_id);
297 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 275 glTexParameterf(dest_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
298 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 276 glTexParameterf(dest_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 277 glTexParameteri(dest_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 278 glTexParameteri(dest_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
301 glCopyTexImage2D(GL_TEXTURE_2D, 0 /* level */, dest_internal_format, 279 glCopyTexImage2D(dest_target, 0 /* level */, dest_internal_format,
302 0 /* x */, 0 /* y */, width, height, 0 /* border */); 280 0 /* x */, 0 /* y */, width, height, 0 /* border */);
303 } 281 }
304 282
305 decoder->RestoreTextureState(source_id); 283 decoder->RestoreTextureState(source_id);
306 decoder->RestoreTextureState(dest_id); 284 decoder->RestoreTextureState(dest_id);
307 decoder->RestoreTextureUnitBindings(0); 285 decoder->RestoreTextureUnitBindings(0);
308 decoder->RestoreActiveTexture(); 286 decoder->RestoreActiveTexture();
309 decoder->RestoreFramebufferBindings(); 287 decoder->RestoreFramebufferBindings();
310 } 288 }
311 289
312 void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder, 290 void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder,
313 GLenum source_target, 291 GLenum source_target,
314 GLuint source_id, 292 GLuint source_id,
293 GLenum dest_target,
315 GLuint dest_id, 294 GLuint dest_id,
316 GLint xoffset, 295 GLint xoffset,
317 GLint yoffset, 296 GLint yoffset,
318 GLint source_x, 297 GLint source_x,
319 GLint source_y, 298 GLint source_y,
320 GLsizei source_width, 299 GLsizei source_width,
321 GLsizei source_height, 300 GLsizei source_height,
322 GLuint framebuffer) { 301 GLuint framebuffer) {
323 DCHECK(source_target == GL_TEXTURE_2D || 302 DCHECK(source_target == GL_TEXTURE_2D ||
324 source_target == GL_TEXTURE_RECTANGLE_ARB); 303 source_target == GL_TEXTURE_RECTANGLE_ARB);
304 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), dest_target);
325 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { 305 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) {
326 glBindTexture(GL_TEXTURE_2D, dest_id); 306 glBindTexture(dest_target, dest_id);
327 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 307 glTexParameterf(dest_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
328 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 308 glTexParameterf(dest_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
329 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 309 glTexParameteri(dest_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
330 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 310 glTexParameteri(dest_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
331 glCopyTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, xoffset, yoffset, 311 glCopyTexSubImage2D(dest_target, 0 /* level */, xoffset, yoffset,
332 source_x, source_y, source_width, source_height); 312 source_x, source_y, source_width, source_height);
333 } 313 }
334 314
335 decoder->RestoreTextureState(source_id); 315 decoder->RestoreTextureState(source_id);
336 decoder->RestoreTextureState(dest_id); 316 decoder->RestoreTextureState(dest_id);
337 decoder->RestoreTextureUnitBindings(0); 317 decoder->RestoreTextureUnitBindings(0);
338 decoder->RestoreActiveTexture(); 318 decoder->RestoreActiveTexture();
339 decoder->RestoreFramebufferBindings(); 319 decoder->RestoreFramebufferBindings();
340 } 320 }
341 321
342 } // namespace 322 } // namespace
343 323
344 namespace gpu { 324 namespace gpu {
345 325
346 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() 326 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager()
347 : initialized_(false), 327 : initialized_(false),
348 vertex_shaders_(NUM_VERTEX_SHADERS, 0u), 328 vertex_shader_(0u),
349 fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u), 329 fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u),
350 buffer_id_(0u), 330 buffer_id_(0u),
351 framebuffer_(0u) {} 331 framebuffer_(0u) {}
352 332
353 CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() { 333 CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() {
354 // |buffer_id_| and |framebuffer_| can be not-null because when GPU context is 334 // |buffer_id_| and |framebuffer_| can be not-null because when GPU context is
355 // lost, this class can be deleted without releasing resources like 335 // lost, this class can be deleted without releasing resources like
356 // GLES2DecoderImpl. 336 // GLES2DecoderImpl.
357 } 337 }
358 338
(...skipping 23 matching lines...) Expand all
382 initialized_ = true; 362 initialized_ = true;
383 } 363 }
384 364
385 void CopyTextureCHROMIUMResourceManager::Destroy() { 365 void CopyTextureCHROMIUMResourceManager::Destroy() {
386 if (!initialized_) 366 if (!initialized_)
387 return; 367 return;
388 368
389 glDeleteFramebuffersEXT(1, &framebuffer_); 369 glDeleteFramebuffersEXT(1, &framebuffer_);
390 framebuffer_ = 0; 370 framebuffer_ = 0;
391 371
392 std::for_each(vertex_shaders_.begin(), vertex_shaders_.end(), DeleteShader); 372 DeleteShader(vertex_shader_);
393 std::for_each( 373 std::for_each(
394 fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader); 374 fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader);
395 375
396 for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end(); 376 for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end();
397 ++it) { 377 ++it) {
398 const ProgramInfo& info = it->second; 378 const ProgramInfo& info = it->second;
399 glDeleteProgram(info.program); 379 glDeleteProgram(info.program);
400 } 380 }
401 381
402 glDeleteBuffersARB(1, &buffer_id_); 382 glDeleteBuffersARB(1, &buffer_id_);
403 buffer_id_ = 0; 383 buffer_id_ = 0;
404 } 384 }
405 385
406 void CopyTextureCHROMIUMResourceManager::DoCopyTexture( 386 void CopyTextureCHROMIUMResourceManager::DoCopyTexture(
407 const gles2::GLES2Decoder* decoder, 387 const gles2::GLES2Decoder* decoder,
408 GLenum source_target, 388 GLenum source_target,
409 GLuint source_id, 389 GLuint source_id,
410 GLenum source_internal_format, 390 GLenum source_internal_format,
391 GLenum dest_target,
411 GLuint dest_id, 392 GLuint dest_id,
412 GLenum dest_internal_format, 393 GLenum dest_internal_format,
413 GLsizei width, 394 GLsizei width,
414 GLsizei height, 395 GLsizei height,
415 bool flip_y, 396 bool flip_y,
416 bool premultiply_alpha, 397 bool premultiply_alpha,
417 bool unpremultiply_alpha) { 398 bool unpremultiply_alpha) {
418 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; 399 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha;
419 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's 400 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's
420 // format does not contain a superset of the components required by the base 401 // format does not contain a superset of the components required by the base
421 // format of internalformat. 402 // format of internalformat.
422 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml 403 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml
423 bool source_format_contain_superset_of_dest_format = 404 bool source_format_contain_superset_of_dest_format =
424 (source_internal_format == dest_internal_format && 405 (source_internal_format == dest_internal_format &&
425 source_internal_format != GL_BGRA_EXT) || 406 source_internal_format != GL_BGRA_EXT) ||
426 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); 407 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB);
427 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, 408 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2,
428 // so restrict this to GL_TEXTURE_2D. 409 // so restrict this to GL_TEXTURE_2D.
429 if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change && 410 if (source_target == GL_TEXTURE_2D && dest_target == GL_TEXTURE_2D &&
411 !flip_y && !premultiply_alpha_change &&
430 source_format_contain_superset_of_dest_format) { 412 source_format_contain_superset_of_dest_format) {
431 DoCopyTexImage2D(decoder, 413 DoCopyTexImage2D(decoder,
432 source_target, 414 source_target,
433 source_id, 415 source_id,
416 dest_target,
434 dest_id, 417 dest_id,
435 dest_internal_format, 418 dest_internal_format,
436 width, 419 width,
437 height, 420 height,
438 framebuffer_); 421 framebuffer_);
439 return; 422 return;
440 } 423 }
441 424
442 // Use kIdentityMatrix if no transform passed in. 425 // Use kIdentityMatrix if no transform passed in.
443 DoCopyTextureWithTransform(decoder, source_target, source_id, dest_id, width, 426 DoCopyTextureWithTransform(decoder, source_target, source_id, dest_target,
444 height, flip_y, premultiply_alpha, 427 dest_id, width, height, flip_y, premultiply_alpha,
445 unpremultiply_alpha, kIdentityMatrix); 428 unpremultiply_alpha, kIdentityMatrix);
446 } 429 }
447 430
448 void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( 431 void CopyTextureCHROMIUMResourceManager::DoCopySubTexture(
449 const gles2::GLES2Decoder* decoder, 432 const gles2::GLES2Decoder* decoder,
450 GLenum source_target, 433 GLenum source_target,
451 GLuint source_id, 434 GLuint source_id,
452 GLenum source_internal_format, 435 GLenum source_internal_format,
436 GLenum dest_target,
453 GLuint dest_id, 437 GLuint dest_id,
454 GLenum dest_internal_format, 438 GLenum dest_internal_format,
455 GLint xoffset, 439 GLint xoffset,
456 GLint yoffset, 440 GLint yoffset,
457 GLint x, 441 GLint x,
458 GLint y, 442 GLint y,
459 GLsizei width, 443 GLsizei width,
460 GLsizei height, 444 GLsizei height,
461 GLsizei dest_width, 445 GLsizei dest_width,
462 GLsizei dest_height, 446 GLsizei dest_height,
463 GLsizei source_width, 447 GLsizei source_width,
464 GLsizei source_height, 448 GLsizei source_height,
465 bool flip_y, 449 bool flip_y,
466 bool premultiply_alpha, 450 bool premultiply_alpha,
467 bool unpremultiply_alpha) { 451 bool unpremultiply_alpha) {
468 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; 452 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha;
469 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's 453 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's
470 // format does not contain a superset of the components required by the base 454 // format does not contain a superset of the components required by the base
471 // format of internalformat. 455 // format of internalformat.
472 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml 456 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml
473 bool source_format_contain_superset_of_dest_format = 457 bool source_format_contain_superset_of_dest_format =
474 (source_internal_format == dest_internal_format && 458 (source_internal_format == dest_internal_format &&
475 source_internal_format != GL_BGRA_EXT) || 459 source_internal_format != GL_BGRA_EXT) ||
476 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); 460 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB);
477 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, 461 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2,
478 // so restrict this to GL_TEXTURE_2D. 462 // so restrict this to GL_TEXTURE_2D.
479 if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change && 463 if (source_target == GL_TEXTURE_2D && dest_target == GL_TEXTURE_2D &&
464 !flip_y && !premultiply_alpha_change &&
480 source_format_contain_superset_of_dest_format) { 465 source_format_contain_superset_of_dest_format) {
481 DoCopyTexSubImage2D(decoder, source_target, source_id, dest_id, xoffset, 466 DoCopyTexSubImage2D(decoder, source_target, source_id, dest_target, dest_id,
482 yoffset, x, y, width, height, framebuffer_); 467 xoffset, yoffset, x, y, width, height, framebuffer_);
483 return; 468 return;
484 } 469 }
485 470
486 DoCopyTextureInternal(decoder, source_target, source_id, dest_id, xoffset, 471 DoCopyTextureInternal(decoder, source_target, source_id, dest_target, dest_id,
487 yoffset, x, y, width, height, dest_width, dest_height, 472 xoffset, yoffset, x, y, width, height, dest_width, dest_height,
488 source_width, source_height, flip_y, premultiply_alpha, 473 source_width, source_height, flip_y, premultiply_alpha,
489 unpremultiply_alpha, kIdentityMatrix); 474 unpremultiply_alpha, kIdentityMatrix);
490 } 475 }
491 476
492 void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( 477 void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
493 const gles2::GLES2Decoder* decoder, 478 const gles2::GLES2Decoder* decoder,
494 GLenum source_target, 479 GLenum source_target,
495 GLuint source_id, 480 GLuint source_id,
481 GLenum dest_target,
496 GLuint dest_id, 482 GLuint dest_id,
497 GLsizei width, 483 GLsizei width,
498 GLsizei height, 484 GLsizei height,
499 bool flip_y, 485 bool flip_y,
500 bool premultiply_alpha, 486 bool premultiply_alpha,
501 bool unpremultiply_alpha, 487 bool unpremultiply_alpha,
502 const GLfloat transform_matrix[16]) { 488 const GLfloat transform_matrix[16]) {
503 GLsizei dest_width = width; 489 GLsizei dest_width = width;
504 GLsizei dest_height = height; 490 GLsizei dest_height = height;
505 DoCopyTextureInternal(decoder, source_target, source_id, dest_id, 0, 0, 0, 0, 491 DoCopyTextureInternal(decoder, source_target, source_id, dest_target, dest_id,
506 width, height, dest_width, dest_height, width, height, 492 0, 0, 0, 0, width, height, dest_width, dest_height,
507 flip_y, premultiply_alpha, unpremultiply_alpha, 493 width, height, flip_y, premultiply_alpha,
508 transform_matrix); 494 unpremultiply_alpha, transform_matrix);
509 } 495 }
510 496
511 void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( 497 void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal(
512 const gles2::GLES2Decoder* decoder, 498 const gles2::GLES2Decoder* decoder,
513 GLenum source_target, 499 GLenum source_target,
514 GLuint source_id, 500 GLuint source_id,
501 GLenum dest_target,
515 GLuint dest_id, 502 GLuint dest_id,
516 GLint xoffset, 503 GLint xoffset,
517 GLint yoffset, 504 GLint yoffset,
518 GLint x, 505 GLint x,
519 GLint y, 506 GLint y,
520 GLsizei width, 507 GLsizei width,
521 GLsizei height, 508 GLsizei height,
522 GLsizei dest_width, 509 GLsizei dest_width,
523 GLsizei dest_height, 510 GLsizei dest_height,
524 GLsizei source_width, 511 GLsizei source_width,
525 GLsizei source_height, 512 GLsizei source_height,
526 bool flip_y, 513 bool flip_y,
527 bool premultiply_alpha, 514 bool premultiply_alpha,
528 bool unpremultiply_alpha, 515 bool unpremultiply_alpha,
529 const GLfloat transform_matrix[16]) { 516 const GLfloat transform_matrix[16]) {
530 DCHECK(source_target == GL_TEXTURE_2D || 517 DCHECK(source_target == GL_TEXTURE_2D ||
531 source_target == GL_TEXTURE_RECTANGLE_ARB || 518 source_target == GL_TEXTURE_RECTANGLE_ARB ||
532 source_target == GL_TEXTURE_EXTERNAL_OES); 519 source_target == GL_TEXTURE_EXTERNAL_OES);
520 DCHECK(dest_target == GL_TEXTURE_2D ||
521 dest_target == GL_TEXTURE_RECTANGLE_ARB);
533 DCHECK_GE(xoffset, 0); 522 DCHECK_GE(xoffset, 0);
534 DCHECK_LE(xoffset + width, dest_width); 523 DCHECK_LE(xoffset + width, dest_width);
535 DCHECK_GE(yoffset, 0); 524 DCHECK_GE(yoffset, 0);
536 DCHECK_LE(yoffset + height, dest_height); 525 DCHECK_LE(yoffset + height, dest_height);
526 if (dest_width == 0 || dest_height == 0 || source_width == 0 ||
527 source_height == 0) {
528 return;
529 }
530
537 if (!initialized_) { 531 if (!initialized_) {
538 DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager."; 532 DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager.";
539 return; 533 return;
540 } 534 }
541 535
542 VertexShaderId vertex_shader_id = GetVertexShaderId(flip_y);
543 DCHECK_LT(static_cast<size_t>(vertex_shader_id), vertex_shaders_.size());
544 FragmentShaderId fragment_shader_id = GetFragmentShaderId( 536 FragmentShaderId fragment_shader_id = GetFragmentShaderId(
545 premultiply_alpha, unpremultiply_alpha, source_target); 537 premultiply_alpha, unpremultiply_alpha, source_target);
546 DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size()); 538 DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size());
547 539
548 ProgramMapKey key(vertex_shader_id, fragment_shader_id); 540 ProgramMapKey key(fragment_shader_id);
549 ProgramInfo* info = &programs_[key]; 541 ProgramInfo* info = &programs_[key];
550 // Create program if necessary. 542 // Create program if necessary.
551 if (!info->program) { 543 if (!info->program) {
552 info->program = glCreateProgram(); 544 info->program = glCreateProgram();
553 GLuint* vertex_shader = &vertex_shaders_[vertex_shader_id]; 545 if (!vertex_shader_) {
554 if (!*vertex_shader) { 546 vertex_shader_ = glCreateShader(GL_VERTEX_SHADER);
555 *vertex_shader = glCreateShader(GL_VERTEX_SHADER); 547 std::string source = GetVertexShaderSource();
556 std::string source = GetVertexShaderSource(flip_y); 548 CompileShader(vertex_shader_, source.c_str());
557 CompileShader(*vertex_shader, source.c_str());
558 } 549 }
559 glAttachShader(info->program, *vertex_shader); 550 glAttachShader(info->program, vertex_shader_);
560 GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id]; 551 GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id];
561 if (!*fragment_shader) { 552 if (!*fragment_shader) {
562 *fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 553 *fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
563 std::string source = GetFragmentShaderSource( 554 std::string source = GetFragmentShaderSource(
564 premultiply_alpha, unpremultiply_alpha, source_target); 555 premultiply_alpha, unpremultiply_alpha, source_target);
565 CompileShader(*fragment_shader, source.c_str()); 556 CompileShader(*fragment_shader, source.c_str());
566 } 557 }
567 glAttachShader(info->program, *fragment_shader); 558 glAttachShader(info->program, *fragment_shader);
568 glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position"); 559 glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position");
569 glLinkProgram(info->program); 560 glLinkProgram(info->program);
570 #ifndef NDEBUG 561 #ifndef NDEBUG
571 GLint linked; 562 GLint linked;
572 glGetProgramiv(info->program, GL_LINK_STATUS, &linked); 563 glGetProgramiv(info->program, GL_LINK_STATUS, &linked);
573 if (!linked) 564 if (!linked)
574 DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure."; 565 DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure.";
575 #endif 566 #endif
576 info->vertex_translate_handle = glGetUniformLocation(info->program, 567 info->vertex_dest_mult_handle =
577 "u_vertex_translate"); 568 glGetUniformLocation(info->program, "u_vertex_dest_mult");
569 info->vertex_dest_add_handle =
570 glGetUniformLocation(info->program, "u_vertex_dest_add");
571 info->vertex_source_mult_handle =
572 glGetUniformLocation(info->program, "u_vertex_source_mult");
573 info->vertex_source_add_handle =
574 glGetUniformLocation(info->program, "u_vertex_source_add");
575
578 info->tex_coord_transform_handle = 576 info->tex_coord_transform_handle =
579 glGetUniformLocation(info->program, "u_tex_coord_transform"); 577 glGetUniformLocation(info->program, "u_tex_coord_transform");
580 info->half_size_handle = glGetUniformLocation(info->program, "u_half_size");
581 info->sampler_handle = glGetUniformLocation(info->program, "u_sampler"); 578 info->sampler_handle = glGetUniformLocation(info->program, "u_sampler");
582 } 579 }
583 glUseProgram(info->program); 580 glUseProgram(info->program);
584 581
585 glUniformMatrix4fv(info->tex_coord_transform_handle, 1, GL_FALSE, 582 glUniformMatrix4fv(info->tex_coord_transform_handle, 1, GL_FALSE,
586 transform_matrix); 583 transform_matrix);
587 584
588 GLint x_translate = xoffset - x; 585 // Note: For simplicity, the calculations in this comment block use a single
589 GLint y_translate = yoffset - y; 586 // dimension. All calculations trivially extend to the x-y plane.
590 if (!x_translate && !y_translate) { 587 // The target subrange in the destination texture has coordinates
591 glUniform2f(info->vertex_translate_handle, 0.0f, 0.0f); 588 // [xoffset, xoffset + width]. The full destination texture has range
592 } else { 589 // [0, dest_width].
593 // transform offsets from ([0, dest_width], [0, dest_height]) coord. 590 //
594 // to ([-1, 1], [-1, 1]) coord. 591 // We want to find A and B such that:
595 GLfloat x_translate_on_vertex = ((2.f * x_translate) / dest_width); 592 // A * X + B = Y
596 GLfloat y_translate_on_vertex = ((2.f * y_translate) / dest_height); 593 // C * Y + D = Z
594 //
595 // where X = [-1, 1], Z = [xoffset, xoffset + width]
596 // and C, D satisfy the relationship C * [-1, 1] + D = [0, dest_width].
597 //
598 // Math shows:
599 // C = D = dest_width / 2
600 // Y = [(xoffset * 2 / dest_width) - 1,
601 // (xoffset + width) * 2 / dest_width) - 1]
602 // A = width / dest_width
603 // B = (xoffset * 2 + width - dest_width) / dest_width
604 glUniform2f(info->vertex_dest_mult_handle, width * 1.f / dest_width,
605 height * 1.f / dest_height);
606 glUniform2f(info->vertex_dest_add_handle,
607 (xoffset * 2.f + width - dest_width) / dest_width,
608 (yoffset * 2.f + height - dest_height) / dest_height);
597 609
598 // Pass translation to the shader program. 610 // Note: For simplicity, the calculations in this comment block use a single
599 glUniform2f(info->vertex_translate_handle, x_translate_on_vertex, 611 // dimension. All calculations trivially extend to the x-y plane.
600 y_translate_on_vertex); 612 // The target subrange in the source texture has coordinates [x, x + width].
601 } 613 // The full source texture has range [0, source_width]. We need to transform
602 if (source_target == GL_TEXTURE_RECTANGLE_ARB) 614 // the subrange into texture space ([0, M]), assuming that [0, source_width]
603 glUniform2f(info->half_size_handle, source_width / 2.0f, 615 // gets mapped to [0, M]. If source_target == GL_TEXTURE_RECTANGLE_ARB, M =
604 source_height / 2.0f); 616 // source_width. Otherwise, M = 1.
605 else 617 //
606 glUniform2f(info->half_size_handle, 0.5f, 0.5f); 618 // We want to find A and B such that:
619 // A * X + B = Y
620 // C * Y + D = Z
621 //
622 // where X = [-1, 1], Z = [x, x + width]
623 // and C, D satisfy the relationship C * [0, M] + D = [0, source_width].
624 //
625 // Math shows:
626 // D = 0
627 // C = source_width / M
628 // Y = [x * M / source_width, (x + width) * M / source_width]
629 // B = (x + w/2) * M / source_width
630 // A = (w/2) * M / source_width
631 //
632 // When flip_y is true, we run the same calcluation, but with Z = [x + width,
633 // x]. (I'm intentionally keeping the x-plane notation, although the
634 // calculation only gets applied to the y-plane).
635 //
636 // Math shows:
637 // D = 0
638 // C = source_width / M
639 // Y = [(x + width) * M / source_width, x * M / source_width]
640 // B = (x + w/2) * M / source_width
641 // A = (-w/2) * M / source_width
642 //
643 // So everything is the same but the sign of A is flipped.
644 GLfloat m_x = source_target == GL_TEXTURE_RECTANGLE_ARB ? source_width : 1;
645 GLfloat m_y = source_target == GL_TEXTURE_RECTANGLE_ARB ? source_height : 1;
646 GLfloat sign_a = flip_y ? -1 : 1;
647 glUniform2f(info->vertex_source_mult_handle, width / 2.f * m_x / source_width,
648 height / 2.f * m_y / source_height * sign_a);
649 glUniform2f(info->vertex_source_add_handle,
650 (x + width / 2.f) * m_x / source_width,
651 (y + height / 2.f) * m_y / source_height);
607 652
608 if (BindFramebufferTexture2D(GL_TEXTURE_2D, dest_id, framebuffer_)) { 653 if (BindFramebufferTexture2D(dest_target, dest_id, framebuffer_)) {
609 #ifndef NDEBUG 654 #ifndef NDEBUG
610 // glValidateProgram of MACOSX validates FBO unlike other platforms, so 655 // glValidateProgram of MACOSX validates FBO unlike other platforms, so
611 // glValidateProgram must be called after FBO binding. crbug.com/463439 656 // glValidateProgram must be called after FBO binding. crbug.com/463439
612 glValidateProgram(info->program); 657 glValidateProgram(info->program);
613 GLint validation_status; 658 GLint validation_status;
614 glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status); 659 glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status);
615 if (GL_TRUE != validation_status) { 660 if (GL_TRUE != validation_status) {
616 DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader."; 661 DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader.";
617 return; 662 return;
618 } 663 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 decoder->RestoreTextureState(dest_id); 704 decoder->RestoreTextureState(dest_id);
660 decoder->RestoreTextureUnitBindings(0); 705 decoder->RestoreTextureUnitBindings(0);
661 decoder->RestoreActiveTexture(); 706 decoder->RestoreActiveTexture();
662 decoder->RestoreProgramBindings(); 707 decoder->RestoreProgramBindings();
663 decoder->RestoreBufferBindings(); 708 decoder->RestoreBufferBindings();
664 decoder->RestoreFramebufferBindings(); 709 decoder->RestoreFramebufferBindings();
665 decoder->RestoreGlobalState(); 710 decoder->RestoreGlobalState();
666 } 711 }
667 712
668 } // namespace gpu 713 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h ('k') | gpu/command_buffer/service/gles2_cmd_decoder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698