OLD | NEW |
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 <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "gpu/command_buffer/service/gl_utils.h" | 10 #include "gpu/command_buffer/service/gl_utils.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 "#define TextureLookup texture2DRect\n" SHADER(src) | 25 "#define TextureLookup texture2DRect\n" SHADER(src) |
26 #define SHADER_EXTERNAL_OES(src) \ | 26 #define SHADER_EXTERNAL_OES(src) \ |
27 "#extension GL_OES_EGL_image_external : require\n" \ | 27 "#extension GL_OES_EGL_image_external : require\n" \ |
28 "#define SamplerType samplerExternalOES\n" \ | 28 "#define SamplerType samplerExternalOES\n" \ |
29 "#define TextureLookup texture2D\n" SHADER(src) | 29 "#define TextureLookup texture2D\n" SHADER(src) |
30 #define FRAGMENT_SHADERS(src) \ | 30 #define FRAGMENT_SHADERS(src) \ |
31 SHADER_2D(src), SHADER_RECTANGLE_ARB(src), SHADER_EXTERNAL_OES(src) | 31 SHADER_2D(src), SHADER_RECTANGLE_ARB(src), SHADER_EXTERNAL_OES(src) |
32 | 32 |
33 namespace { | 33 namespace { |
34 | 34 |
| 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}; |
| 39 |
35 enum VertexShaderId { | 40 enum VertexShaderId { |
36 VERTEX_SHADER_COPY_TEXTURE, | 41 VERTEX_SHADER_COPY_TEXTURE, |
37 VERTEX_SHADER_COPY_TEXTURE_FLIP_Y, | 42 VERTEX_SHADER_COPY_TEXTURE_FLIP_Y, |
38 NUM_VERTEX_SHADERS, | 43 NUM_VERTEX_SHADERS, |
39 }; | 44 }; |
40 | 45 |
41 enum FragmentShaderId { | 46 enum FragmentShaderId { |
42 FRAGMENT_SHADER_COPY_TEXTURE_2D, | 47 FRAGMENT_SHADER_COPY_TEXTURE_2D, |
43 FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB, | 48 FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB, |
44 FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES, | 49 FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES, |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 0 /* border */); | 246 0 /* border */); |
242 } | 247 } |
243 | 248 |
244 decoder->RestoreTextureState(source_id); | 249 decoder->RestoreTextureState(source_id); |
245 decoder->RestoreTextureState(dest_id); | 250 decoder->RestoreTextureState(dest_id); |
246 decoder->RestoreTextureUnitBindings(0); | 251 decoder->RestoreTextureUnitBindings(0); |
247 decoder->RestoreActiveTexture(); | 252 decoder->RestoreActiveTexture(); |
248 decoder->RestoreFramebufferBindings(); | 253 decoder->RestoreFramebufferBindings(); |
249 } | 254 } |
250 | 255 |
| 256 void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder, |
| 257 GLenum source_target, |
| 258 GLuint source_id, |
| 259 GLuint dest_id, |
| 260 GLint dest_level, |
| 261 GLint xoffset, |
| 262 GLint yoffset, |
| 263 GLsizei source_width, |
| 264 GLsizei source_height, |
| 265 GLuint framebuffer) { |
| 266 DCHECK(source_target == GL_TEXTURE_2D || |
| 267 source_target == GL_TEXTURE_RECTANGLE_ARB); |
| 268 if (BindFramebufferTexture2D(source_target, source_id, 0 /* level */, |
| 269 framebuffer)) { |
| 270 glBindTexture(GL_TEXTURE_2D, dest_id); |
| 271 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 272 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 273 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 274 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 275 glCopyTexSubImage2D(GL_TEXTURE_2D, dest_level, xoffset, yoffset, 0 /* x */, |
| 276 0 /* y */, source_width, source_height); |
| 277 } |
| 278 |
| 279 decoder->RestoreTextureState(source_id); |
| 280 decoder->RestoreTextureState(dest_id); |
| 281 decoder->RestoreTextureUnitBindings(0); |
| 282 decoder->RestoreActiveTexture(); |
| 283 decoder->RestoreFramebufferBindings(); |
| 284 } |
| 285 |
| 286 // Copy from SkMatrix44::preTranslate |
| 287 void PreTranslate(GLfloat* matrix, GLfloat dx, GLfloat dy, GLfloat dz) { |
| 288 if (!dx && !dy && !dz) |
| 289 return; |
| 290 |
| 291 for (int i = 0; i < 4; ++i) { |
| 292 matrix[(3 * 4) + i] = matrix[(0 * 4) + i] * dx + matrix[(1 * 4) + i] * dy + |
| 293 matrix[(2 * 4) + i] * dz + matrix[(3 * 4) + i]; |
| 294 } |
| 295 } |
| 296 |
251 } // namespace | 297 } // namespace |
252 | 298 |
253 namespace gpu { | 299 namespace gpu { |
254 | 300 |
255 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() | 301 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() |
256 : initialized_(false), | 302 : initialized_(false), |
257 vertex_shaders_(NUM_VERTEX_SHADERS, 0u), | 303 vertex_shaders_(NUM_VERTEX_SHADERS, 0u), |
258 fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u), | 304 fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u), |
259 buffer_id_(0u), | 305 buffer_id_(0u), |
260 framebuffer_(0u) {} | 306 framebuffer_(0u) {} |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 source_id, | 389 source_id, |
344 dest_id, | 390 dest_id, |
345 dest_level, | 391 dest_level, |
346 dest_internal_format, | 392 dest_internal_format, |
347 width, | 393 width, |
348 height, | 394 height, |
349 framebuffer_); | 395 framebuffer_); |
350 return; | 396 return; |
351 } | 397 } |
352 | 398 |
353 // Use default transform matrix if no transform passed in. | 399 // Use kIdentityMatrix if no transform passed in. |
354 const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, | 400 DoCopyTextureWithTransform( |
355 0.0f, 1.0f, 0.0f, 0.0f, | 401 decoder, source_target, source_id, dest_id, dest_level, width, height, |
356 0.0f, 0.0f, 1.0f, 0.0f, | 402 flip_y, premultiply_alpha, unpremultiply_alpha, kIdentityMatrix); |
357 0.0f, 0.0f, 0.0f, 1.0f}; | 403 } |
358 DoCopyTextureWithTransform(decoder, | 404 |
359 source_target, | 405 void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( |
360 source_id, | 406 const gles2::GLES2Decoder* decoder, |
361 dest_id, | 407 GLenum source_target, |
362 dest_level, | 408 GLuint source_id, |
363 width, | 409 GLenum source_internal_format, |
364 height, | 410 GLuint dest_id, |
365 flip_y, | 411 GLint dest_level, |
366 premultiply_alpha, | 412 GLenum dest_internal_format, |
367 unpremultiply_alpha, | 413 GLint xoffset, |
368 default_matrix); | 414 GLint yoffset, |
| 415 GLsizei dest_width, |
| 416 GLsizei dest_height, |
| 417 GLsizei source_width, |
| 418 GLsizei source_height, |
| 419 bool flip_y, |
| 420 bool premultiply_alpha, |
| 421 bool unpremultiply_alpha) { |
| 422 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; |
| 423 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's |
| 424 // format does not contain a superset of the components required by the base |
| 425 // format of internalformat. |
| 426 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml |
| 427 bool source_format_contain_superset_of_dest_format = |
| 428 (source_internal_format == dest_internal_format && |
| 429 source_internal_format != GL_BGRA_EXT) || |
| 430 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); |
| 431 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, |
| 432 // so restrict this to GL_TEXTURE_2D. |
| 433 if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change && |
| 434 source_format_contain_superset_of_dest_format) { |
| 435 DoCopyTexSubImage2D(decoder, source_target, source_id, dest_id, dest_level, |
| 436 xoffset, yoffset, source_width, source_height, |
| 437 framebuffer_); |
| 438 return; |
| 439 } |
| 440 |
| 441 // Use kIdentityMatrix if no transform passed in. |
| 442 DoCopySubTextureWithTransform( |
| 443 decoder, source_target, source_id, dest_id, dest_level, xoffset, yoffset, |
| 444 dest_width, dest_height, source_width, source_height, flip_y, |
| 445 premultiply_alpha, unpremultiply_alpha, kIdentityMatrix); |
369 } | 446 } |
370 | 447 |
371 void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( | 448 void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( |
372 const gles2::GLES2Decoder* decoder, | 449 const gles2::GLES2Decoder* decoder, |
373 GLenum source_target, | 450 GLenum source_target, |
374 GLuint source_id, | 451 GLuint source_id, |
375 GLuint dest_id, | 452 GLuint dest_id, |
376 GLint dest_level, | 453 GLint dest_level, |
377 GLsizei width, | 454 GLsizei width, |
378 GLsizei height, | 455 GLsizei height, |
379 bool flip_y, | 456 bool flip_y, |
380 bool premultiply_alpha, | 457 bool premultiply_alpha, |
381 bool unpremultiply_alpha, | 458 bool unpremultiply_alpha, |
382 const GLfloat transform_matrix[16]) { | 459 const GLfloat transform_matrix[16]) { |
| 460 GLsizei dest_width = width; |
| 461 GLsizei dest_height = height; |
| 462 DoCopyTextureInternal(decoder, source_target, source_id, dest_id, dest_level, |
| 463 0, 0, dest_width, dest_height, width, height, flip_y, |
| 464 premultiply_alpha, unpremultiply_alpha, |
| 465 transform_matrix); |
| 466 } |
| 467 |
| 468 void CopyTextureCHROMIUMResourceManager::DoCopySubTextureWithTransform( |
| 469 const gles2::GLES2Decoder* decoder, |
| 470 GLenum source_target, |
| 471 GLuint source_id, |
| 472 GLuint dest_id, |
| 473 GLint dest_level, |
| 474 GLint xoffset, |
| 475 GLint yoffset, |
| 476 GLsizei dest_width, |
| 477 GLsizei dest_height, |
| 478 GLsizei source_width, |
| 479 GLsizei source_height, |
| 480 bool flip_y, |
| 481 bool premultiply_alpha, |
| 482 bool unpremultiply_alpha, |
| 483 const GLfloat transform_matrix[16]) { |
| 484 DoCopyTextureInternal(decoder, source_target, source_id, dest_id, dest_level, |
| 485 xoffset, yoffset, dest_width, dest_height, source_width, |
| 486 source_height, flip_y, premultiply_alpha, |
| 487 unpremultiply_alpha, transform_matrix); |
| 488 } |
| 489 |
| 490 void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( |
| 491 const gles2::GLES2Decoder* decoder, |
| 492 GLenum source_target, |
| 493 GLuint source_id, |
| 494 GLuint dest_id, |
| 495 GLint dest_level, |
| 496 GLint xoffset, |
| 497 GLint yoffset, |
| 498 GLsizei dest_width, |
| 499 GLsizei dest_height, |
| 500 GLsizei source_width, |
| 501 GLsizei source_height, |
| 502 bool flip_y, |
| 503 bool premultiply_alpha, |
| 504 bool unpremultiply_alpha, |
| 505 const GLfloat transform_matrix[16]) { |
383 DCHECK(source_target == GL_TEXTURE_2D || | 506 DCHECK(source_target == GL_TEXTURE_2D || |
384 source_target == GL_TEXTURE_RECTANGLE_ARB || | 507 source_target == GL_TEXTURE_RECTANGLE_ARB || |
385 source_target == GL_TEXTURE_EXTERNAL_OES); | 508 source_target == GL_TEXTURE_EXTERNAL_OES); |
| 509 DCHECK(xoffset >= 0 && xoffset + source_width <= dest_width); |
| 510 DCHECK(yoffset >= 0 && yoffset + source_height <= dest_height); |
386 if (!initialized_) { | 511 if (!initialized_) { |
387 DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager."; | 512 DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager."; |
388 return; | 513 return; |
389 } | 514 } |
390 | 515 |
391 VertexShaderId vertex_shader_id = GetVertexShaderId(flip_y); | 516 VertexShaderId vertex_shader_id = GetVertexShaderId(flip_y); |
392 DCHECK_LT(static_cast<size_t>(vertex_shader_id), vertex_shaders_.size()); | 517 DCHECK_LT(static_cast<size_t>(vertex_shader_id), vertex_shaders_.size()); |
393 FragmentShaderId fragment_shader_id = GetFragmentShaderId( | 518 FragmentShaderId fragment_shader_id = GetFragmentShaderId( |
394 premultiply_alpha, unpremultiply_alpha, source_target); | 519 premultiply_alpha, unpremultiply_alpha, source_target); |
395 DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size()); | 520 DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 #ifndef NDEBUG | 554 #ifndef NDEBUG |
430 glValidateProgram(info->program); | 555 glValidateProgram(info->program); |
431 GLint validation_status; | 556 GLint validation_status; |
432 glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status); | 557 glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status); |
433 if (GL_TRUE != validation_status) { | 558 if (GL_TRUE != validation_status) { |
434 DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader."; | 559 DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader."; |
435 return; | 560 return; |
436 } | 561 } |
437 #endif | 562 #endif |
438 | 563 |
439 glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, transform_matrix); | 564 if (!xoffset && !yoffset) { |
| 565 glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, transform_matrix); |
| 566 } else { |
| 567 // transform offsets from ([0, dest_width], [0, dest_height]) coord. |
| 568 // to ([-1, 1], [-1, 1]) coord. |
| 569 GLfloat xoffset_on_vertex = ((2.f * xoffset) / dest_width); |
| 570 GLfloat yoffset_on_vertex = ((2.f * yoffset) / dest_height); |
| 571 |
| 572 // Pass view_matrix * offset_matrix to the program. |
| 573 GLfloat view_transform[16]; |
| 574 memcpy(view_transform, transform_matrix, 16 * sizeof(GLfloat)); |
| 575 PreTranslate(view_transform, xoffset_on_vertex, yoffset_on_vertex, 0); |
| 576 glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, view_transform); |
| 577 } |
440 if (source_target == GL_TEXTURE_RECTANGLE_ARB) | 578 if (source_target == GL_TEXTURE_RECTANGLE_ARB) |
441 glUniform2f(info->half_size_handle, width / 2.0f, height / 2.0f); | 579 glUniform2f(info->half_size_handle, source_width / 2.0f, |
| 580 source_height / 2.0f); |
442 else | 581 else |
443 glUniform2f(info->half_size_handle, 0.5f, 0.5f); | 582 glUniform2f(info->half_size_handle, 0.5f, 0.5f); |
444 | 583 |
445 if (BindFramebufferTexture2D( | 584 if (BindFramebufferTexture2D( |
446 GL_TEXTURE_2D, dest_id, dest_level, framebuffer_)) { | 585 GL_TEXTURE_2D, dest_id, dest_level, framebuffer_)) { |
447 decoder->ClearAllAttributes(); | 586 decoder->ClearAllAttributes(); |
448 glEnableVertexAttribArray(kVertexPositionAttrib); | 587 glEnableVertexAttribArray(kVertexPositionAttrib); |
449 | 588 |
450 glBindBuffer(GL_ARRAY_BUFFER, buffer_id_); | 589 glBindBuffer(GL_ARRAY_BUFFER, buffer_id_); |
451 glVertexAttribPointer(kVertexPositionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); | 590 glVertexAttribPointer(kVertexPositionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); |
452 | 591 |
453 glUniform1i(info->sampler_handle, 0); | 592 glUniform1i(info->sampler_handle, 0); |
454 | 593 |
455 glBindTexture(source_target, source_id); | 594 glBindTexture(source_target, source_id); |
456 glTexParameterf(source_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 595 glTexParameterf(source_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
457 glTexParameterf(source_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 596 glTexParameterf(source_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
458 glTexParameteri(source_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 597 glTexParameteri(source_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
459 glTexParameteri(source_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 598 glTexParameteri(source_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
460 | 599 |
461 glDisable(GL_DEPTH_TEST); | 600 glDisable(GL_DEPTH_TEST); |
462 glDisable(GL_SCISSOR_TEST); | 601 glDisable(GL_SCISSOR_TEST); |
463 glDisable(GL_STENCIL_TEST); | 602 glDisable(GL_STENCIL_TEST); |
464 glDisable(GL_CULL_FACE); | 603 glDisable(GL_CULL_FACE); |
465 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | 604 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
466 glDepthMask(GL_FALSE); | 605 glDepthMask(GL_FALSE); |
467 glDisable(GL_BLEND); | 606 glDisable(GL_BLEND); |
468 | 607 |
469 glViewport(0, 0, width, height); | 608 glViewport(0, 0, dest_width, dest_height); |
470 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | 609 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
471 } | 610 } |
472 | 611 |
473 decoder->RestoreAllAttributes(); | 612 decoder->RestoreAllAttributes(); |
474 decoder->RestoreTextureState(source_id); | 613 decoder->RestoreTextureState(source_id); |
475 decoder->RestoreTextureState(dest_id); | 614 decoder->RestoreTextureState(dest_id); |
476 decoder->RestoreTextureUnitBindings(0); | 615 decoder->RestoreTextureUnitBindings(0); |
477 decoder->RestoreActiveTexture(); | 616 decoder->RestoreActiveTexture(); |
478 decoder->RestoreProgramBindings(); | 617 decoder->RestoreProgramBindings(); |
479 decoder->RestoreBufferBindings(); | 618 decoder->RestoreBufferBindings(); |
480 decoder->RestoreFramebufferBindings(); | 619 decoder->RestoreFramebufferBindings(); |
481 decoder->RestoreGlobalState(); | 620 decoder->RestoreGlobalState(); |
482 } | 621 } |
483 | 622 |
484 } // namespace gpu | 623 } // namespace gpu |
OLD | NEW |