gl_renderer.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2010 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. 4 5#include "cc/output/gl_renderer.h" 6 7#include <algorithm> 8#include <limits> 9#include <set> 10#include <string> 11#include <vector> 12 13#include "base/debug/trace_event.h" 14#include "base/logging.h" 15#include "base/strings/string_split.h" 16#include "base/strings/string_util.h" 17#include "base/strings/stringprintf.h" 18#include "build/build_config.h" 19#include "cc/base/math_util.h" 20#include "cc/layers/video_layer_impl.h" 21#include "cc/output/compositor_frame.h" 22#include "cc/output/compositor_frame_metadata.h" 23#include "cc/output/context_provider.h" 24#include "cc/output/copy_output_request.h" 25#include "cc/output/geometry_binding.h" 26#include "cc/output/gl_frame_data.h" 27#include "cc/output/output_surface.h" 28#include "cc/output/render_surface_filters.h" 29#include "cc/quads/picture_draw_quad.h" 30#include "cc/quads/render_pass.h" 31#include "cc/quads/stream_video_draw_quad.h" 32#include "cc/quads/texture_draw_quad.h" 33#include "cc/resources/layer_quad.h" 34#include "cc/resources/scoped_resource.h" 35#include "cc/resources/texture_mailbox_deleter.h" 36#include "cc/trees/damage_tracker.h" 37#include "cc/trees/proxy.h" 38#include "cc/trees/single_thread_proxy.h" 39#include "gpu/GLES2/gl2extchromium.h" 40#include "gpu/command_buffer/client/context_support.h" 41#include "gpu/command_buffer/client/gles2_interface.h" 42#include "gpu/command_buffer/common/gpu_memory_allocation.h" 43#include "third_party/khronos/GLES2/gl2.h" 44#include "third_party/khronos/GLES2/gl2ext.h" 45#include "third_party/skia/include/core/SkBitmap.h" 46#include "third_party/skia/include/core/SkColor.h" 47#include "third_party/skia/include/core/SkColorFilter.h" 48#include "third_party/skia/include/core/SkSurface.h" 49#include "third_party/skia/include/gpu/GrContext.h" 50#include "third_party/skia/include/gpu/GrTexture.h" 51#include "third_party/skia/include/gpu/SkGpuDevice.h" 52#include "third_party/skia/include/gpu/SkGrTexturePixelRef.h" 53#include "third_party/skia/include/gpu/gl/GrGLInterface.h" 54#include "ui/gfx/quad_f.h" 55#include "ui/gfx/rect_conversions.h" 56 57using gpu::gles2::GLES2Interface; 58 59namespace cc { 60 61namespace { 62 63// TODO(epenner): This should probably be moved to output surface. 64// 65// This implements a simple fence based on client side swaps. 66// This is to isolate the ResourceProvider from 'frames' which 67// it shouldn't need to care about, while still allowing us to 68// enforce good texture recycling behavior strictly throughout 69// the compositor (don't recycle a texture while it's in use). 70class SimpleSwapFence : public ResourceProvider::Fence { 71 public: 72 SimpleSwapFence() : has_passed_(false) {} 73 virtual bool HasPassed() OVERRIDE { return has_passed_; } 74 void SetHasPassed() { has_passed_ = true; } 75 76 private: 77 virtual ~SimpleSwapFence() {} 78 bool has_passed_; 79}; 80 81class OnDemandRasterTaskImpl : public internal::Task { 82 public: 83 OnDemandRasterTaskImpl(PicturePileImpl* picture_pile, 84 SkBitmap* bitmap, 85 gfx::Rect content_rect, 86 float contents_scale) 87 : picture_pile_(picture_pile), 88 bitmap_(bitmap), 89 content_rect_(content_rect), 90 contents_scale_(contents_scale) { 91 DCHECK(picture_pile_); 92 DCHECK(bitmap_); 93 } 94 95 // Overridden from internal::Task: 96 virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE { 97 TRACE_EVENT0("cc", "OnDemandRasterTaskImpl::RunOnWorkerThread"); 98 SkBitmapDevice device(*bitmap_); 99 SkCanvas canvas(&device); 100 picture_pile_->RasterToBitmap( 101 &canvas, content_rect_, contents_scale_, NULL); 102 } 103 104 protected: 105 virtual ~OnDemandRasterTaskImpl() {} 106 107 private: 108 PicturePileImpl* picture_pile_; 109 SkBitmap* bitmap_; 110 const gfx::Rect content_rect_; 111 const float contents_scale_; 112 113 DISALLOW_COPY_AND_ASSIGN(OnDemandRasterTaskImpl); 114}; 115 116bool NeedsIOSurfaceReadbackWorkaround() { 117#if defined(OS_MACOSX) 118 // This isn't strictly required in DumpRenderTree-mode when Mesa is used, 119 // but it doesn't seem to hurt. 120 return true; 121#else 122 return false; 123#endif 124} 125 126Float4 UVTransform(const TextureDrawQuad* quad) { 127 gfx::PointF uv0 = quad->uv_top_left; 128 gfx::PointF uv1 = quad->uv_bottom_right; 129 Float4 xform = {{uv0.x(), uv0.y(), uv1.x() - uv0.x(), uv1.y() - uv0.y()}}; 130 if (quad->flipped) { 131 xform.data[1] = 1.0f - xform.data[1]; 132 xform.data[3] = -xform.data[3]; 133 } 134 return xform; 135} 136 137Float4 PremultipliedColor(SkColor color) { 138 const float factor = 1.0f / 255.0f; 139 const float alpha = SkColorGetA(color) * factor; 140 141 Float4 result = { 142 {SkColorGetR(color) * factor * alpha, SkColorGetG(color) * factor * alpha, 143 SkColorGetB(color) * factor * alpha, alpha}}; 144 return result; 145} 146 147SamplerType SamplerTypeFromTextureTarget(GLenum target) { 148 switch (target) { 149 case GL_TEXTURE_2D: 150 return SamplerType2D; 151 case GL_TEXTURE_RECTANGLE_ARB: 152 return SamplerType2DRect; 153 case GL_TEXTURE_EXTERNAL_OES: 154 return SamplerTypeExternalOES; 155 default: 156 NOTREACHED(); 157 return SamplerType2D; 158 } 159} 160 161// Smallest unit that impact anti-aliasing output. We use this to 162// determine when anti-aliasing is unnecessary. 163const float kAntiAliasingEpsilon = 1.0f / 1024.0f; 164 165} // anonymous namespace 166 167struct GLRenderer::PendingAsyncReadPixels { 168 PendingAsyncReadPixels() : buffer(0) {} 169 170 scoped_ptr<CopyOutputRequest> copy_request; 171 base::CancelableClosure finished_read_pixels_callback; 172 unsigned buffer; 173 174 private: 175 DISALLOW_COPY_AND_ASSIGN(PendingAsyncReadPixels); 176}; 177 178scoped_ptr<GLRenderer> GLRenderer::Create( 179 RendererClient* client, 180 const LayerTreeSettings* settings, 181 OutputSurface* output_surface, 182 ResourceProvider* resource_provider, 183 TextureMailboxDeleter* texture_mailbox_deleter, 184 int highp_threshold_min) { 185 return make_scoped_ptr(new GLRenderer(client, 186 settings, 187 output_surface, 188 resource_provider, 189 texture_mailbox_deleter, 190 highp_threshold_min)); 191} 192 193GLRenderer::GLRenderer(RendererClient* client, 194 const LayerTreeSettings* settings, 195 OutputSurface* output_surface, 196 ResourceProvider* resource_provider, 197 TextureMailboxDeleter* texture_mailbox_deleter, 198 int highp_threshold_min) 199 : DirectRenderer(client, settings, output_surface, resource_provider), 200 offscreen_framebuffer_id_(0), 201 shared_geometry_quad_(gfx::RectF(-0.5f, -0.5f, 1.0f, 1.0f)), 202 gl_(output_surface->context_provider()->ContextGL()), 203 context_support_(output_surface->context_provider()->ContextSupport()), 204 texture_mailbox_deleter_(texture_mailbox_deleter), 205 is_backbuffer_discarded_(false), 206 visible_(true), 207 is_scissor_enabled_(false), 208 scissor_rect_needs_reset_(true), 209 stencil_shadow_(false), 210 blend_shadow_(false), 211 highp_threshold_min_(highp_threshold_min), 212 highp_threshold_cache_(0), 213 on_demand_tile_raster_resource_id_(0) { 214 DCHECK(gl_); 215 DCHECK(context_support_); 216 217 ContextProvider::Capabilities context_caps = 218 output_surface_->context_provider()->ContextCapabilities(); 219 220 capabilities_.using_partial_swap = 221 settings_->partial_swap_enabled && context_caps.gpu.post_sub_buffer; 222 223 DCHECK(!context_caps.gpu.iosurface || context_caps.gpu.texture_rectangle); 224 225 capabilities_.using_egl_image = context_caps.gpu.egl_image_external; 226 227 capabilities_.max_texture_size = resource_provider_->max_texture_size(); 228 capabilities_.best_texture_format = resource_provider_->best_texture_format(); 229 230 // The updater can access textures while the GLRenderer is using them. 231 capabilities_.allow_partial_texture_updates = true; 232 233 // Check for texture fast paths. Currently we always use MO8 textures, 234 // so we only need to avoid POT textures if we have an NPOT fast-path. 235 capabilities_.avoid_pow2_textures = context_caps.gpu.fast_npot_mo8_textures; 236 237 capabilities_.using_offscreen_context3d = true; 238 239 capabilities_.using_map_image = 240 settings_->use_map_image && context_caps.gpu.map_image; 241 242 capabilities_.using_discard_framebuffer = 243 context_caps.gpu.discard_framebuffer; 244 245 capabilities_.allow_rasterize_on_demand = true; 246 247 InitializeSharedObjects(); 248} 249 250GLRenderer::~GLRenderer() { 251 while (!pending_async_read_pixels_.empty()) { 252 PendingAsyncReadPixels* pending_read = pending_async_read_pixels_.back(); 253 pending_read->finished_read_pixels_callback.Cancel(); 254 pending_async_read_pixels_.pop_back(); 255 } 256 257 CleanupSharedObjects(); 258} 259 260const RendererCapabilitiesImpl& GLRenderer::Capabilities() const { 261 return capabilities_; 262} 263 264void GLRenderer::DebugGLCall(GLES2Interface* gl, 265 const char* command, 266 const char* file, 267 int line) { 268 GLuint error = gl->GetError(); 269 if (error != GL_NO_ERROR) 270 LOG(ERROR) << "GL command failed: File: " << file << "\n\tLine " << line 271 << "\n\tcommand: " << command << ", error " 272 << static_cast<int>(error) << "\n"; 273} 274 275void GLRenderer::SetVisible(bool visible) { 276 if (visible_ == visible) 277 return; 278 visible_ = visible; 279 280 EnforceMemoryPolicy(); 281 282 context_support_->SetSurfaceVisible(visible); 283} 284 285void GLRenderer::SendManagedMemoryStats(size_t bytes_visible, 286 size_t bytes_visible_and_nearby, 287 size_t bytes_allocated) { 288 gpu::ManagedMemoryStats stats; 289 stats.bytes_required = bytes_visible; 290 stats.bytes_nice_to_have = bytes_visible_and_nearby; 291 stats.bytes_allocated = bytes_allocated; 292 stats.backbuffer_requested = !is_backbuffer_discarded_; 293 context_support_->SendManagedMemoryStats(stats); 294} 295 296void GLRenderer::ReleaseRenderPassTextures() { render_pass_textures_.clear(); } 297 298void GLRenderer::DiscardPixels(bool has_external_stencil_test, 299 bool draw_rect_covers_full_surface) { 300 if (has_external_stencil_test || !draw_rect_covers_full_surface || 301 !capabilities_.using_discard_framebuffer) 302 return; 303 bool using_default_framebuffer = 304 !current_framebuffer_lock_ && 305 output_surface_->capabilities().uses_default_gl_framebuffer; 306 GLenum attachments[] = {static_cast<GLenum>( 307 using_default_framebuffer ? GL_COLOR_EXT : GL_COLOR_ATTACHMENT0_EXT)}; 308 gl_->DiscardFramebufferEXT( 309 GL_FRAMEBUFFER, arraysize(attachments), attachments); 310} 311 312void GLRenderer::ClearFramebuffer(DrawingFrame* frame, 313 bool has_external_stencil_test) { 314 // It's unsafe to clear when we have a stencil test because glClear ignores 315 // stencil. 316 if (has_external_stencil_test) { 317 DCHECK(!frame->current_render_pass->has_transparent_background); 318 return; 319 } 320 321 // On DEBUG builds, opaque render passes are cleared to blue to easily see 322 // regions that were not drawn on the screen. 323 if (frame->current_render_pass->has_transparent_background) 324 GLC(gl_, gl_->ClearColor(0, 0, 0, 0)); 325 else 326 GLC(gl_, gl_->ClearColor(0, 0, 1, 1)); 327 328 bool always_clear = false; 329#ifndef NDEBUG 330 always_clear = true; 331#endif 332 if (always_clear || frame->current_render_pass->has_transparent_background) { 333 GLbitfield clear_bits = GL_COLOR_BUFFER_BIT; 334 if (always_clear) 335 clear_bits |= GL_STENCIL_BUFFER_BIT; 336 gl_->Clear(clear_bits); 337 } 338} 339 340void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) { 341 if (frame->device_viewport_rect.IsEmpty()) 342 return; 343 344 TRACE_EVENT0("cc", "GLRenderer::BeginDrawingFrame"); 345 346 // TODO(enne): Do we need to reinitialize all of this state per frame? 347 ReinitializeGLState(); 348} 349 350void GLRenderer::DoNoOp() { 351 GLC(gl_, gl_->BindFramebuffer(GL_FRAMEBUFFER, 0)); 352 GLC(gl_, gl_->Flush()); 353} 354 355void GLRenderer::DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) { 356 DCHECK(quad->rect.Contains(quad->visible_rect)); 357 if (quad->material != DrawQuad::TEXTURE_CONTENT) { 358 FlushTextureQuadCache(); 359 } 360 361 switch (quad->material) { 362 case DrawQuad::INVALID: 363 NOTREACHED(); 364 break; 365 case DrawQuad::CHECKERBOARD: 366 DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad)); 367 break; 368 case DrawQuad::DEBUG_BORDER: 369 DrawDebugBorderQuad(frame, DebugBorderDrawQuad::MaterialCast(quad)); 370 break; 371 case DrawQuad::IO_SURFACE_CONTENT: 372 DrawIOSurfaceQuad(frame, IOSurfaceDrawQuad::MaterialCast(quad)); 373 break; 374 case DrawQuad::PICTURE_CONTENT: 375 DrawPictureQuad(frame, PictureDrawQuad::MaterialCast(quad)); 376 break; 377 case DrawQuad::RENDER_PASS: 378 DrawRenderPassQuad(frame, RenderPassDrawQuad::MaterialCast(quad)); 379 break; 380 case DrawQuad::SOLID_COLOR: 381 DrawSolidColorQuad(frame, SolidColorDrawQuad::MaterialCast(quad)); 382 break; 383 case DrawQuad::STREAM_VIDEO_CONTENT: 384 DrawStreamVideoQuad(frame, StreamVideoDrawQuad::MaterialCast(quad)); 385 break; 386 case DrawQuad::SURFACE_CONTENT: 387 // Surface content should be fully resolved to other quad types before 388 // reaching a direct renderer. 389 NOTREACHED(); 390 break; 391 case DrawQuad::TEXTURE_CONTENT: 392 EnqueueTextureQuad(frame, TextureDrawQuad::MaterialCast(quad)); 393 break; 394 case DrawQuad::TILED_CONTENT: 395 DrawTileQuad(frame, TileDrawQuad::MaterialCast(quad)); 396 break; 397 case DrawQuad::YUV_VIDEO_CONTENT: 398 DrawYUVVideoQuad(frame, YUVVideoDrawQuad::MaterialCast(quad)); 399 break; 400 } 401} 402 403void GLRenderer::DrawCheckerboardQuad(const DrawingFrame* frame, 404 const CheckerboardDrawQuad* quad) { 405 SetBlendEnabled(quad->ShouldDrawWithBlending()); 406 407 const TileCheckerboardProgram* program = GetTileCheckerboardProgram(); 408 DCHECK(program && (program->initialized() || IsContextLost())); 409 SetUseProgram(program->program()); 410 411 SkColor color = quad->color; 412 GLC(gl_, 413 gl_->Uniform4f(program->fragment_shader().color_location(), 414 SkColorGetR(color) * (1.0f / 255.0f), 415 SkColorGetG(color) * (1.0f / 255.0f), 416 SkColorGetB(color) * (1.0f / 255.0f), 417 1)); 418 419 const int checkerboard_width = 16; 420 float frequency = 1.0f / checkerboard_width; 421 422 gfx::Rect tile_rect = quad->rect; 423 float tex_offset_x = tile_rect.x() % checkerboard_width; 424 float tex_offset_y = tile_rect.y() % checkerboard_width; 425 float tex_scale_x = tile_rect.width(); 426 float tex_scale_y = tile_rect.height(); 427 GLC(gl_, 428 gl_->Uniform4f(program->fragment_shader().tex_transform_location(), 429 tex_offset_x, 430 tex_offset_y, 431 tex_scale_x, 432 tex_scale_y)); 433 434 GLC(gl_, 435 gl_->Uniform1f(program->fragment_shader().frequency_location(), 436 frequency)); 437 438 SetShaderOpacity(quad->opacity(), 439 program->fragment_shader().alpha_location()); 440 DrawQuadGeometry(frame, 441 quad->quadTransform(), 442 quad->rect, 443 program->vertex_shader().matrix_location()); 444} 445 446void GLRenderer::DrawDebugBorderQuad(const DrawingFrame* frame, 447 const DebugBorderDrawQuad* quad) { 448 SetBlendEnabled(quad->ShouldDrawWithBlending()); 449 450 static float gl_matrix[16]; 451 const DebugBorderProgram* program = GetDebugBorderProgram(); 452 DCHECK(program && (program->initialized() || IsContextLost())); 453 SetUseProgram(program->program()); 454 455 // Use the full quad_rect for debug quads to not move the edges based on 456 // partial swaps. 457 gfx::Rect layer_rect = quad->rect; 458 gfx::Transform render_matrix = quad->quadTransform(); 459 render_matrix.Translate(0.5f * layer_rect.width() + layer_rect.x(), 460 0.5f * layer_rect.height() + layer_rect.y()); 461 render_matrix.Scale(layer_rect.width(), layer_rect.height()); 462 GLRenderer::ToGLMatrix(&gl_matrix[0], 463 frame->projection_matrix * render_matrix); 464 GLC(gl_, 465 gl_->UniformMatrix4fv( 466 program->vertex_shader().matrix_location(), 1, false, &gl_matrix[0])); 467 468 SkColor color = quad->color; 469 float alpha = SkColorGetA(color) * (1.0f / 255.0f); 470 471 GLC(gl_, 472 gl_->Uniform4f(program->fragment_shader().color_location(), 473 (SkColorGetR(color) * (1.0f / 255.0f)) * alpha, 474 (SkColorGetG(color) * (1.0f / 255.0f)) * alpha, 475 (SkColorGetB(color) * (1.0f / 255.0f)) * alpha, 476 alpha)); 477 478 GLC(gl_, gl_->LineWidth(quad->width)); 479 480 // The indices for the line are stored in the same array as the triangle 481 // indices. 482 GLC(gl_, gl_->DrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 0)); 483} 484 485static SkBitmap ApplyImageFilter(GLRenderer* renderer, 486 ContextProvider* offscreen_contexts, 487 gfx::Point origin, 488 SkImageFilter* filter, 489 ScopedResource* source_texture_resource) { 490 if (!filter) 491 return SkBitmap(); 492 493 if (!offscreen_contexts || !offscreen_contexts->GrContext()) 494 return SkBitmap(); 495 496 ResourceProvider::ScopedWriteLockGL lock(renderer->resource_provider(), 497 source_texture_resource->id()); 498 499 // Flush the compositor context to ensure that textures there are available 500 // in the shared context. Do this after locking/creating the compositor 501 // texture. 502 renderer->resource_provider()->Flush(); 503 504 // Wrap the source texture in a Ganesh platform texture. 505 GrBackendTextureDesc backend_texture_description; 506 backend_texture_description.fWidth = source_texture_resource->size().width(); 507 backend_texture_description.fHeight = 508 source_texture_resource->size().height(); 509 backend_texture_description.fConfig = kSkia8888_GrPixelConfig; 510 backend_texture_description.fTextureHandle = lock.texture_id(); 511 backend_texture_description.fOrigin = kBottomLeft_GrSurfaceOrigin; 512 skia::RefPtr<GrTexture> texture = 513 skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture( 514 backend_texture_description)); 515 516 SkImageInfo info = { 517 source_texture_resource->size().width(), 518 source_texture_resource->size().height(), 519 kPMColor_SkColorType, 520 kPremul_SkAlphaType 521 }; 522 // Place the platform texture inside an SkBitmap. 523 SkBitmap source; 524 source.setConfig(info); 525 skia::RefPtr<SkGrPixelRef> pixel_ref = 526 skia::AdoptRef(new SkGrPixelRef(info, texture.get())); 527 source.setPixelRef(pixel_ref.get()); 528 529 // Create a scratch texture for backing store. 530 GrTextureDesc desc; 531 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 532 desc.fSampleCnt = 0; 533 desc.fWidth = source.width(); 534 desc.fHeight = source.height(); 535 desc.fConfig = kSkia8888_GrPixelConfig; 536 desc.fOrigin = kBottomLeft_GrSurfaceOrigin; 537 GrAutoScratchTexture scratch_texture( 538 offscreen_contexts->GrContext(), desc, GrContext::kExact_ScratchTexMatch); 539 skia::RefPtr<GrTexture> backing_store = 540 skia::AdoptRef(scratch_texture.detach()); 541 542 // Create a device and canvas using that backing store. 543 SkGpuDevice device(offscreen_contexts->GrContext(), backing_store.get()); 544 SkCanvas canvas(&device); 545 546 // Draw the source bitmap through the filter to the canvas. 547 SkPaint paint; 548 paint.setImageFilter(filter); 549 canvas.clear(SK_ColorTRANSPARENT); 550 551 // TODO(senorblanco): in addition to the origin translation here, the canvas 552 // should also be scaled to accomodate device pixel ratio and pinch zoom. See 553 // crbug.com/281516 and crbug.com/281518. 554 canvas.translate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y())); 555 canvas.drawSprite(source, 0, 0, &paint); 556 557 // Flush skia context so that all the rendered stuff appears on the 558 // texture. 559 offscreen_contexts->GrContext()->flush(); 560 561 // Flush the GL context so rendering results from this context are 562 // visible in the compositor's context. 563 offscreen_contexts->ContextGL()->Flush(); 564 565 return device.accessBitmap(false); 566} 567 568static SkBitmap ApplyBlendModeWithBackdrop( 569 GLRenderer* renderer, 570 ContextProvider* offscreen_contexts, 571 SkBitmap source_bitmap_with_filters, 572 ScopedResource* source_texture_resource, 573 ScopedResource* background_texture_resource, 574 SkXfermode::Mode blend_mode) { 575 if (!offscreen_contexts || !offscreen_contexts->GrContext()) 576 return source_bitmap_with_filters; 577 578 DCHECK(background_texture_resource); 579 DCHECK(source_texture_resource); 580 581 gfx::Size source_size = source_texture_resource->size(); 582 gfx::Size background_size = background_texture_resource->size(); 583 584 DCHECK_LE(background_size.width(), source_size.width()); 585 DCHECK_LE(background_size.height(), source_size.height()); 586 587 int source_texture_with_filters_id; 588 scoped_ptr<ResourceProvider::ScopedReadLockGL> lock; 589 if (source_bitmap_with_filters.getTexture()) { 590 DCHECK_EQ(source_size.width(), source_bitmap_with_filters.width()); 591 DCHECK_EQ(source_size.height(), source_bitmap_with_filters.height()); 592 GrTexture* texture = 593 reinterpret_cast<GrTexture*>(source_bitmap_with_filters.getTexture()); 594 source_texture_with_filters_id = texture->getTextureHandle(); 595 } else { 596 lock.reset(new ResourceProvider::ScopedReadLockGL( 597 renderer->resource_provider(), source_texture_resource->id())); 598 source_texture_with_filters_id = lock->texture_id(); 599 } 600 601 ResourceProvider::ScopedReadLockGL lock_background( 602 renderer->resource_provider(), background_texture_resource->id()); 603 604 // Flush the compositor context to ensure that textures there are available 605 // in the shared context. Do this after locking/creating the compositor 606 // texture. 607 renderer->resource_provider()->Flush(); 608 609 // Wrap the source texture in a Ganesh platform texture. 610 GrBackendTextureDesc backend_texture_description; 611 backend_texture_description.fConfig = kSkia8888_GrPixelConfig; 612 backend_texture_description.fOrigin = kBottomLeft_GrSurfaceOrigin; 613 614 backend_texture_description.fWidth = source_size.width(); 615 backend_texture_description.fHeight = source_size.height(); 616 backend_texture_description.fTextureHandle = source_texture_with_filters_id; 617 skia::RefPtr<GrTexture> source_texture = 618 skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture( 619 backend_texture_description)); 620 621 backend_texture_description.fWidth = background_size.width(); 622 backend_texture_description.fHeight = background_size.height(); 623 backend_texture_description.fTextureHandle = lock_background.texture_id(); 624 skia::RefPtr<GrTexture> background_texture = 625 skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture( 626 backend_texture_description)); 627 628 SkImageInfo source_info = { 629 source_size.width(), 630 source_size.height(), 631 kPMColor_SkColorType, 632 kPremul_SkAlphaType 633 }; 634 // Place the platform texture inside an SkBitmap. 635 SkBitmap source; 636 source.setConfig(source_info); 637 skia::RefPtr<SkGrPixelRef> source_pixel_ref = 638 skia::AdoptRef(new SkGrPixelRef(source_info, source_texture.get())); 639 source.setPixelRef(source_pixel_ref.get()); 640 641 SkImageInfo background_info = { 642 background_size.width(), 643 background_size.height(), 644 kPMColor_SkColorType, 645 kPremul_SkAlphaType 646 }; 647 648 SkBitmap background; 649 background.setConfig(background_info); 650 skia::RefPtr<SkGrPixelRef> background_pixel_ref = 651 skia::AdoptRef(new SkGrPixelRef( 652 background_info, background_texture.get())); 653 background.setPixelRef(background_pixel_ref.get()); 654 655 // Create a scratch texture for backing store. 656 GrTextureDesc desc; 657 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 658 desc.fSampleCnt = 0; 659 desc.fWidth = source.width(); 660 desc.fHeight = source.height(); 661 desc.fConfig = kSkia8888_GrPixelConfig; 662 desc.fOrigin = kBottomLeft_GrSurfaceOrigin; 663 GrAutoScratchTexture scratch_texture( 664 offscreen_contexts->GrContext(), desc, GrContext::kExact_ScratchTexMatch); 665 skia::RefPtr<GrTexture> backing_store = 666 skia::AdoptRef(scratch_texture.detach()); 667 668 // Create a device and canvas using that backing store. 669 SkGpuDevice device(offscreen_contexts->GrContext(), backing_store.get()); 670 SkCanvas canvas(&device); 671 672 // Draw the source bitmap through the filter to the canvas. 673 canvas.clear(SK_ColorTRANSPARENT); 674 canvas.drawSprite(background, 0, 0); 675 SkPaint paint; 676 paint.setXfermodeMode(blend_mode); 677 canvas.drawSprite(source, 0, 0, &paint); 678 679 // Flush skia context so that all the rendered stuff appears on the 680 // texture. 681 offscreen_contexts->GrContext()->flush(); 682 683 // Flush the GL context so rendering results from this context are 684 // visible in the compositor's context. 685 offscreen_contexts->ContextGL()->Flush(); 686 687 return device.accessBitmap(false); 688} 689 690scoped_ptr<ScopedResource> GLRenderer::GetBackgroundWithFilters( 691 DrawingFrame* frame, 692 const RenderPassDrawQuad* quad, 693 const gfx::Transform& contents_device_transform, 694 const gfx::Transform& contents_device_transform_inverse, 695 bool* background_changed) { 696 // This method draws a background filter, which applies a filter to any pixels 697 // behind the quad and seen through its background. The algorithm works as 698 // follows: 699 // 1. Compute a bounding box around the pixels that will be visible through 700 // the quad. 701 // 2. Read the pixels in the bounding box into a buffer R. 702 // 3. Apply the background filter to R, so that it is applied in the pixels' 703 // coordinate space. 704 // 4. Apply the quad's inverse transform to map the pixels in R into the 705 // quad's content space. This implicitly clips R by the content bounds of the 706 // quad since the destination texture has bounds matching the quad's content. 707 // 5. Draw the background texture for the contents using the same transform as 708 // used to draw the contents itself. This is done without blending to replace 709 // the current background pixels with the new filtered background. 710 // 6. Draw the contents of the quad over drop of the new background with 711 // blending, as per usual. The filtered background pixels will show through 712 // any non-opaque pixels in this draws. 713 // 714 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5. 715 716 // TODO(danakj): When this algorithm changes, update 717 // LayerTreeHost::PrioritizeTextures() accordingly. 718 719 // TODO(danakj): We only allow background filters on an opaque render surface 720 // because other surfaces may contain translucent pixels, and the contents 721 // behind those translucent pixels wouldn't have the filter applied. 722 bool apply_background_filters = 723 !frame->current_render_pass->has_transparent_background; 724 DCHECK(!frame->current_texture); 725 726 // TODO(ajuma): Add support for reference filters once 727 // FilterOperations::GetOutsets supports reference filters. 728 if (apply_background_filters && quad->background_filters.HasReferenceFilter()) 729 apply_background_filters = false; 730 731 // TODO(danakj): Do a single readback for both the surface and replica and 732 // cache the filtered results (once filter textures are not reused). 733 gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( 734 contents_device_transform, SharedGeometryQuad().BoundingBox())); 735 736 int top, right, bottom, left; 737 quad->background_filters.GetOutsets(&top, &right, &bottom, &left); 738 window_rect.Inset(-left, -top, -right, -bottom); 739 740 window_rect.Intersect( 741 MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect)); 742 743 scoped_ptr<ScopedResource> device_background_texture = 744 ScopedResource::Create(resource_provider_); 745 // The TextureUsageFramebuffer hint makes ResourceProvider avoid immutable 746 // storage allocation (texStorage2DEXT) for this texture. copyTexImage2D fails 747 // when called on a texture having immutable storage. 748 device_background_texture->Allocate( 749 window_rect.size(), ResourceProvider::TextureUsageFramebuffer, RGBA_8888); 750 { 751 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, 752 device_background_texture->id()); 753 GetFramebufferTexture( 754 lock.texture_id(), device_background_texture->format(), window_rect); 755 } 756 757 skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter( 758 quad->background_filters, device_background_texture->size()); 759 760 SkBitmap filtered_device_background; 761 if (apply_background_filters) { 762 filtered_device_background = 763 ApplyImageFilter(this, 764 frame->offscreen_context_provider, 765 quad->rect.origin(), 766 filter.get(), 767 device_background_texture.get()); 768 } 769 *background_changed = (filtered_device_background.getTexture() != NULL); 770 771 int filtered_device_background_texture_id = 0; 772 scoped_ptr<ResourceProvider::ScopedReadLockGL> lock; 773 if (filtered_device_background.getTexture()) { 774 GrTexture* texture = 775 reinterpret_cast<GrTexture*>(filtered_device_background.getTexture()); 776 filtered_device_background_texture_id = texture->getTextureHandle(); 777 } else { 778 lock.reset(new ResourceProvider::ScopedReadLockGL( 779 resource_provider_, device_background_texture->id())); 780 filtered_device_background_texture_id = lock->texture_id(); 781 } 782 783 scoped_ptr<ScopedResource> background_texture = 784 ScopedResource::Create(resource_provider_); 785 background_texture->Allocate( 786 quad->rect.size(), ResourceProvider::TextureUsageFramebuffer, RGBA_8888); 787 788 const RenderPass* target_render_pass = frame->current_render_pass; 789 bool using_background_texture = 790 UseScopedTexture(frame, background_texture.get(), quad->rect); 791 792 if (using_background_texture) { 793 // Copy the readback pixels from device to the background texture for the 794 // surface. 795 gfx::Transform device_to_framebuffer_transform; 796 device_to_framebuffer_transform.Translate( 797 quad->rect.width() * 0.5f + quad->rect.x(), 798 quad->rect.height() * 0.5f + quad->rect.y()); 799 device_to_framebuffer_transform.Scale(quad->rect.width(), 800 quad->rect.height()); 801 device_to_framebuffer_transform.PreconcatTransform( 802 contents_device_transform_inverse); 803 804#ifndef NDEBUG 805 GLC(gl_, gl_->ClearColor(0, 0, 1, 1)); 806 gl_->Clear(GL_COLOR_BUFFER_BIT); 807#endif 808 809 // The filtered_deveice_background_texture is oriented the same as the frame 810 // buffer. The transform we are copying with has a vertical flip, as well as 811 // the |device_to_framebuffer_transform|, which cancel each other out. So do 812 // not flip the contents in the shader to maintain orientation. 813 bool flip_vertically = false; 814 815 CopyTextureToFramebuffer(frame, 816 filtered_device_background_texture_id, 817 window_rect, 818 device_to_framebuffer_transform, 819 flip_vertically); 820 } 821 822 UseRenderPass(frame, target_render_pass); 823 824 if (!using_background_texture) 825 return scoped_ptr<ScopedResource>(); 826 return background_texture.Pass(); 827} 828 829void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, 830 const RenderPassDrawQuad* quad) { 831 SetBlendEnabled(quad->ShouldDrawWithBlending()); 832 833 ScopedResource* contents_texture = 834 render_pass_textures_.get(quad->render_pass_id); 835 if (!contents_texture || !contents_texture->id()) 836 return; 837 838 gfx::Transform quad_rect_matrix; 839 QuadRectTransform(&quad_rect_matrix, quad->quadTransform(), quad->rect); 840 gfx::Transform contents_device_transform = 841 frame->window_matrix * frame->projection_matrix * quad_rect_matrix; 842 contents_device_transform.FlattenTo2d(); 843 844 // Can only draw surface if device matrix is invertible. 845 gfx::Transform contents_device_transform_inverse( 846 gfx::Transform::kSkipInitialization); 847 if (!contents_device_transform.GetInverse(&contents_device_transform_inverse)) 848 return; 849 850 bool need_background_texture = 851 quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode || 852 !quad->background_filters.IsEmpty(); 853 bool background_changed = false; 854 scoped_ptr<ScopedResource> background_texture; 855 if (need_background_texture) { 856 // The pixels from the filtered background should completely replace the 857 // current pixel values. 858 bool disable_blending = blend_enabled(); 859 if (disable_blending) 860 SetBlendEnabled(false); 861 862 background_texture = 863 GetBackgroundWithFilters(frame, 864 quad, 865 contents_device_transform, 866 contents_device_transform_inverse, 867 &background_changed); 868 869 if (disable_blending) 870 SetBlendEnabled(true); 871 } 872 873 // TODO(senorblanco): Cache this value so that we don't have to do it for both 874 // the surface and its replica. Apply filters to the contents texture. 875 SkBitmap filter_bitmap; 876 SkScalar color_matrix[20]; 877 bool use_color_matrix = false; 878 // TODO(ajuma): Always use RenderSurfaceFilters::BuildImageFilter, not just 879 // when we have a reference filter. 880 if (!quad->filters.IsEmpty()) { 881 skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter( 882 quad->filters, contents_texture->size()); 883 if (filter) { 884 skia::RefPtr<SkColorFilter> cf; 885 886 { 887 SkColorFilter* colorfilter_rawptr = NULL; 888 filter->asColorFilter(&colorfilter_rawptr); 889 cf = skia::AdoptRef(colorfilter_rawptr); 890 } 891 892 if (cf && cf->asColorMatrix(color_matrix) && !filter->getInput(0)) { 893 // We have a single color matrix as a filter; apply it locally 894 // in the compositor. 895 use_color_matrix = true; 896 } else { 897 filter_bitmap = ApplyImageFilter(this, 898 frame->offscreen_context_provider, 899 quad->rect.origin(), 900 filter.get(), 901 contents_texture); 902 } 903 } 904 } 905 906 if (quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode && 907 background_texture) { 908 filter_bitmap = 909 ApplyBlendModeWithBackdrop(this, 910 frame->offscreen_context_provider, 911 filter_bitmap, 912 contents_texture, 913 background_texture.get(), 914 quad->shared_quad_state->blend_mode); 915 } 916 917 // Draw the background texture if it has some filters applied. 918 if (background_texture && background_changed) { 919 DCHECK(background_texture->size() == quad->rect.size()); 920 ResourceProvider::ScopedReadLockGL lock(resource_provider_, 921 background_texture->id()); 922 923 // The background_texture is oriented the same as the frame buffer. The 924 // transform we are copying with has a vertical flip, so flip the contents 925 // in the shader to maintain orientation 926 bool flip_vertically = true; 927 928 CopyTextureToFramebuffer(frame, 929 lock.texture_id(), 930 quad->rect, 931 quad->quadTransform(), 932 flip_vertically); 933 } 934 935 bool clipped = false; 936 gfx::QuadF device_quad = MathUtil::MapQuad( 937 contents_device_transform, SharedGeometryQuad(), &clipped); 938 LayerQuad device_layer_bounds(gfx::QuadF(device_quad.BoundingBox())); 939 LayerQuad device_layer_edges(device_quad); 940 941 // Use anti-aliasing programs only when necessary. 942 bool use_aa = 943 !clipped && (!device_quad.IsRectilinear() || 944 !gfx::IsNearestRectWithinDistance(device_quad.BoundingBox(), 945 kAntiAliasingEpsilon)); 946 if (use_aa) { 947 device_layer_bounds.InflateAntiAliasingDistance(); 948 device_layer_edges.InflateAntiAliasingDistance(); 949 } 950 951 scoped_ptr<ResourceProvider::ScopedReadLockGL> mask_resource_lock; 952 unsigned mask_texture_id = 0; 953 if (quad->mask_resource_id) { 954 mask_resource_lock.reset(new ResourceProvider::ScopedReadLockGL( 955 resource_provider_, quad->mask_resource_id)); 956 mask_texture_id = mask_resource_lock->texture_id(); 957 } 958 959 // TODO(danakj): use the background_texture and blend the background in with 960 // this draw instead of having a separate copy of the background texture. 961 962 scoped_ptr<ResourceProvider::ScopedSamplerGL> contents_resource_lock; 963 if (filter_bitmap.getTexture()) { 964 GrTexture* texture = 965 reinterpret_cast<GrTexture*>(filter_bitmap.getTexture()); 966 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_)); 967 gl_->BindTexture(GL_TEXTURE_2D, texture->getTextureHandle()); 968 } else { 969 contents_resource_lock = 970 make_scoped_ptr(new ResourceProvider::ScopedSamplerGL( 971 resource_provider_, contents_texture->id(), GL_LINEAR)); 972 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), 973 contents_resource_lock->target()); 974 } 975 976 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 977 gl_, 978 &highp_threshold_cache_, 979 highp_threshold_min_, 980 quad->shared_quad_state->visible_content_rect.bottom_right()); 981 982 int shader_quad_location = -1; 983 int shader_edge_location = -1; 984 int shader_viewport_location = -1; 985 int shader_mask_sampler_location = -1; 986 int shader_mask_tex_coord_scale_location = -1; 987 int shader_mask_tex_coord_offset_location = -1; 988 int shader_matrix_location = -1; 989 int shader_alpha_location = -1; 990 int shader_color_matrix_location = -1; 991 int shader_color_offset_location = -1; 992 int shader_tex_transform_location = -1; 993 994 if (use_aa && mask_texture_id && !use_color_matrix) { 995 const RenderPassMaskProgramAA* program = 996 GetRenderPassMaskProgramAA(tex_coord_precision); 997 SetUseProgram(program->program()); 998 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 999 1000 shader_quad_location = program->vertex_shader().quad_location(); 1001 shader_edge_location = program->vertex_shader().edge_location(); 1002 shader_viewport_location = program->vertex_shader().viewport_location(); 1003 shader_mask_sampler_location = 1004 program->fragment_shader().mask_sampler_location(); 1005 shader_mask_tex_coord_scale_location = 1006 program->fragment_shader().mask_tex_coord_scale_location(); 1007 shader_mask_tex_coord_offset_location = 1008 program->fragment_shader().mask_tex_coord_offset_location(); 1009 shader_matrix_location = program->vertex_shader().matrix_location(); 1010 shader_alpha_location = program->fragment_shader().alpha_location(); 1011 shader_tex_transform_location = 1012 program->vertex_shader().tex_transform_location(); 1013 } else if (!use_aa && mask_texture_id && !use_color_matrix) { 1014 const RenderPassMaskProgram* program = 1015 GetRenderPassMaskProgram(tex_coord_precision); 1016 SetUseProgram(program->program()); 1017 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1018 1019 shader_mask_sampler_location = 1020 program->fragment_shader().mask_sampler_location(); 1021 shader_mask_tex_coord_scale_location = 1022 program->fragment_shader().mask_tex_coord_scale_location(); 1023 shader_mask_tex_coord_offset_location = 1024 program->fragment_shader().mask_tex_coord_offset_location(); 1025 shader_matrix_location = program->vertex_shader().matrix_location(); 1026 shader_alpha_location = program->fragment_shader().alpha_location(); 1027 shader_tex_transform_location = 1028 program->vertex_shader().tex_transform_location(); 1029 } else if (use_aa && !mask_texture_id && !use_color_matrix) { 1030 const RenderPassProgramAA* program = 1031 GetRenderPassProgramAA(tex_coord_precision); 1032 SetUseProgram(program->program()); 1033 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1034 1035 shader_quad_location = program->vertex_shader().quad_location(); 1036 shader_edge_location = program->vertex_shader().edge_location(); 1037 shader_viewport_location = program->vertex_shader().viewport_location(); 1038 shader_matrix_location = program->vertex_shader().matrix_location(); 1039 shader_alpha_location = program->fragment_shader().alpha_location(); 1040 shader_tex_transform_location = 1041 program->vertex_shader().tex_transform_location(); 1042 } else if (use_aa && mask_texture_id && use_color_matrix) { 1043 const RenderPassMaskColorMatrixProgramAA* program = 1044 GetRenderPassMaskColorMatrixProgramAA(tex_coord_precision); 1045 SetUseProgram(program->program()); 1046 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1047 1048 shader_matrix_location = program->vertex_shader().matrix_location(); 1049 shader_quad_location = program->vertex_shader().quad_location(); 1050 shader_tex_transform_location = 1051 program->vertex_shader().tex_transform_location(); 1052 shader_edge_location = program->vertex_shader().edge_location(); 1053 shader_viewport_location = program->vertex_shader().viewport_location(); 1054 shader_alpha_location = program->fragment_shader().alpha_location(); 1055 shader_mask_sampler_location = 1056 program->fragment_shader().mask_sampler_location(); 1057 shader_mask_tex_coord_scale_location = 1058 program->fragment_shader().mask_tex_coord_scale_location(); 1059 shader_mask_tex_coord_offset_location = 1060 program->fragment_shader().mask_tex_coord_offset_location(); 1061 shader_color_matrix_location = 1062 program->fragment_shader().color_matrix_location(); 1063 shader_color_offset_location = 1064 program->fragment_shader().color_offset_location(); 1065 } else if (use_aa && !mask_texture_id && use_color_matrix) { 1066 const RenderPassColorMatrixProgramAA* program = 1067 GetRenderPassColorMatrixProgramAA(tex_coord_precision); 1068 SetUseProgram(program->program()); 1069 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1070 1071 shader_matrix_location = program->vertex_shader().matrix_location(); 1072 shader_quad_location = program->vertex_shader().quad_location(); 1073 shader_tex_transform_location = 1074 program->vertex_shader().tex_transform_location(); 1075 shader_edge_location = program->vertex_shader().edge_location(); 1076 shader_viewport_location = program->vertex_shader().viewport_location(); 1077 shader_alpha_location = program->fragment_shader().alpha_location(); 1078 shader_color_matrix_location = 1079 program->fragment_shader().color_matrix_location(); 1080 shader_color_offset_location = 1081 program->fragment_shader().color_offset_location(); 1082 } else if (!use_aa && mask_texture_id && use_color_matrix) { 1083 const RenderPassMaskColorMatrixProgram* program = 1084 GetRenderPassMaskColorMatrixProgram(tex_coord_precision); 1085 SetUseProgram(program->program()); 1086 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1087 1088 shader_matrix_location = program->vertex_shader().matrix_location(); 1089 shader_tex_transform_location = 1090 program->vertex_shader().tex_transform_location(); 1091 shader_mask_sampler_location = 1092 program->fragment_shader().mask_sampler_location(); 1093 shader_mask_tex_coord_scale_location = 1094 program->fragment_shader().mask_tex_coord_scale_location(); 1095 shader_mask_tex_coord_offset_location = 1096 program->fragment_shader().mask_tex_coord_offset_location(); 1097 shader_alpha_location = program->fragment_shader().alpha_location(); 1098 shader_color_matrix_location = 1099 program->fragment_shader().color_matrix_location(); 1100 shader_color_offset_location = 1101 program->fragment_shader().color_offset_location(); 1102 } else if (!use_aa && !mask_texture_id && use_color_matrix) { 1103 const RenderPassColorMatrixProgram* program = 1104 GetRenderPassColorMatrixProgram(tex_coord_precision); 1105 SetUseProgram(program->program()); 1106 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1107 1108 shader_matrix_location = program->vertex_shader().matrix_location(); 1109 shader_tex_transform_location = 1110 program->vertex_shader().tex_transform_location(); 1111 shader_alpha_location = program->fragment_shader().alpha_location(); 1112 shader_color_matrix_location = 1113 program->fragment_shader().color_matrix_location(); 1114 shader_color_offset_location = 1115 program->fragment_shader().color_offset_location(); 1116 } else { 1117 const RenderPassProgram* program = 1118 GetRenderPassProgram(tex_coord_precision); 1119 SetUseProgram(program->program()); 1120 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1121 1122 shader_matrix_location = program->vertex_shader().matrix_location(); 1123 shader_alpha_location = program->fragment_shader().alpha_location(); 1124 shader_tex_transform_location = 1125 program->vertex_shader().tex_transform_location(); 1126 } 1127 float tex_scale_x = 1128 quad->rect.width() / static_cast<float>(contents_texture->size().width()); 1129 float tex_scale_y = quad->rect.height() / 1130 static_cast<float>(contents_texture->size().height()); 1131 DCHECK_LE(tex_scale_x, 1.0f); 1132 DCHECK_LE(tex_scale_y, 1.0f); 1133 1134 DCHECK(shader_tex_transform_location != -1 || IsContextLost()); 1135 // Flip the content vertically in the shader, as the RenderPass input 1136 // texture is already oriented the same way as the framebuffer, but the 1137 // projection transform does a flip. 1138 GLC(gl_, 1139 gl_->Uniform4f(shader_tex_transform_location, 1140 0.0f, 1141 tex_scale_y, 1142 tex_scale_x, 1143 -tex_scale_y)); 1144 1145 scoped_ptr<ResourceProvider::ScopedSamplerGL> shader_mask_sampler_lock; 1146 if (shader_mask_sampler_location != -1) { 1147 DCHECK_NE(shader_mask_tex_coord_scale_location, 1); 1148 DCHECK_NE(shader_mask_tex_coord_offset_location, 1); 1149 GLC(gl_, gl_->Uniform1i(shader_mask_sampler_location, 1)); 1150 1151 float mask_tex_scale_x = quad->mask_uv_rect.width() / tex_scale_x; 1152 float mask_tex_scale_y = quad->mask_uv_rect.height() / tex_scale_y; 1153 1154 // Mask textures are oriented vertically flipped relative to the framebuffer 1155 // and the RenderPass contents texture, so we flip the tex coords from the 1156 // RenderPass texture to find the mask texture coords. 1157 GLC(gl_, 1158 gl_->Uniform2f(shader_mask_tex_coord_offset_location, 1159 quad->mask_uv_rect.x(), 1160 quad->mask_uv_rect.y() + quad->mask_uv_rect.height())); 1161 GLC(gl_, 1162 gl_->Uniform2f(shader_mask_tex_coord_scale_location, 1163 mask_tex_scale_x, 1164 -mask_tex_scale_y)); 1165 shader_mask_sampler_lock = make_scoped_ptr( 1166 new ResourceProvider::ScopedSamplerGL(resource_provider_, 1167 quad->mask_resource_id, 1168 GL_TEXTURE1, 1169 GL_LINEAR)); 1170 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), 1171 shader_mask_sampler_lock->target()); 1172 } 1173 1174 if (shader_edge_location != -1) { 1175 float edge[24]; 1176 device_layer_edges.ToFloatArray(edge); 1177 device_layer_bounds.ToFloatArray(&edge[12]); 1178 GLC(gl_, gl_->Uniform3fv(shader_edge_location, 8, edge)); 1179 } 1180 1181 if (shader_viewport_location != -1) { 1182 float viewport[4] = {static_cast<float>(viewport_.x()), 1183 static_cast<float>(viewport_.y()), 1184 static_cast<float>(viewport_.width()), 1185 static_cast<float>(viewport_.height()), }; 1186 GLC(gl_, gl_->Uniform4fv(shader_viewport_location, 1, viewport)); 1187 } 1188 1189 if (shader_color_matrix_location != -1) { 1190 float matrix[16]; 1191 for (int i = 0; i < 4; ++i) { 1192 for (int j = 0; j < 4; ++j) 1193 matrix[i * 4 + j] = SkScalarToFloat(color_matrix[j * 5 + i]); 1194 } 1195 GLC(gl_, 1196 gl_->UniformMatrix4fv(shader_color_matrix_location, 1, false, matrix)); 1197 } 1198 static const float kScale = 1.0f / 255.0f; 1199 if (shader_color_offset_location != -1) { 1200 float offset[4]; 1201 for (int i = 0; i < 4; ++i) 1202 offset[i] = SkScalarToFloat(color_matrix[i * 5 + 4]) * kScale; 1203 1204 GLC(gl_, gl_->Uniform4fv(shader_color_offset_location, 1, offset)); 1205 } 1206 1207 // Map device space quad to surface space. contents_device_transform has no 3d 1208 // component since it was flattened, so we don't need to project. 1209 gfx::QuadF surface_quad = MathUtil::MapQuad(contents_device_transform_inverse, 1210 device_layer_edges.ToQuadF(), 1211 &clipped); 1212 1213 SetShaderOpacity(quad->opacity(), shader_alpha_location); 1214 SetShaderQuadF(surface_quad, shader_quad_location); 1215 DrawQuadGeometry( 1216 frame, quad->quadTransform(), quad->rect, shader_matrix_location); 1217 1218 // Flush the compositor context before the filter bitmap goes out of 1219 // scope, so the draw gets processed before the filter texture gets deleted. 1220 if (filter_bitmap.getTexture()) 1221 GLC(gl_, gl_->Flush()); 1222} 1223 1224struct SolidColorProgramUniforms { 1225 unsigned program; 1226 unsigned matrix_location; 1227 unsigned viewport_location; 1228 unsigned quad_location; 1229 unsigned edge_location; 1230 unsigned color_location; 1231}; 1232 1233template <class T> 1234static void SolidColorUniformLocation(T program, 1235 SolidColorProgramUniforms* uniforms) { 1236 uniforms->program = program->program(); 1237 uniforms->matrix_location = program->vertex_shader().matrix_location(); 1238 uniforms->viewport_location = program->vertex_shader().viewport_location(); 1239 uniforms->quad_location = program->vertex_shader().quad_location(); 1240 uniforms->edge_location = program->vertex_shader().edge_location(); 1241 uniforms->color_location = program->fragment_shader().color_location(); 1242} 1243 1244// static 1245bool GLRenderer::SetupQuadForAntialiasing( 1246 const gfx::Transform& device_transform, 1247 const DrawQuad* quad, 1248 gfx::QuadF* local_quad, 1249 float edge[24]) { 1250 gfx::Rect tile_rect = quad->visible_rect; 1251 1252 bool clipped = false; 1253 gfx::QuadF device_layer_quad = MathUtil::MapQuad( 1254 device_transform, gfx::QuadF(quad->visibleContentRect()), &clipped); 1255 1256 bool is_axis_aligned_in_target = device_layer_quad.IsRectilinear(); 1257 bool is_nearest_rect_within_epsilon = 1258 is_axis_aligned_in_target && 1259 gfx::IsNearestRectWithinDistance(device_layer_quad.BoundingBox(), 1260 kAntiAliasingEpsilon); 1261 // AAing clipped quads is not supported by the code yet. 1262 bool use_aa = !clipped && !is_nearest_rect_within_epsilon && quad->IsEdge(); 1263 if (!use_aa) 1264 return false; 1265 1266 LayerQuad device_layer_bounds(gfx::QuadF(device_layer_quad.BoundingBox())); 1267 device_layer_bounds.InflateAntiAliasingDistance(); 1268 1269 LayerQuad device_layer_edges(device_layer_quad); 1270 device_layer_edges.InflateAntiAliasingDistance(); 1271 1272 device_layer_edges.ToFloatArray(edge); 1273 device_layer_bounds.ToFloatArray(&edge[12]); 1274 1275 gfx::PointF bottom_right = tile_rect.bottom_right(); 1276 gfx::PointF bottom_left = tile_rect.bottom_left(); 1277 gfx::PointF top_left = tile_rect.origin(); 1278 gfx::PointF top_right = tile_rect.top_right(); 1279 1280 // Map points to device space. 1281 bottom_right = MathUtil::MapPoint(device_transform, bottom_right, &clipped); 1282 DCHECK(!clipped); 1283 bottom_left = MathUtil::MapPoint(device_transform, bottom_left, &clipped); 1284 DCHECK(!clipped); 1285 top_left = MathUtil::MapPoint(device_transform, top_left, &clipped); 1286 DCHECK(!clipped); 1287 top_right = MathUtil::MapPoint(device_transform, top_right, &clipped); 1288 DCHECK(!clipped); 1289 1290 LayerQuad::Edge bottom_edge(bottom_right, bottom_left); 1291 LayerQuad::Edge left_edge(bottom_left, top_left); 1292 LayerQuad::Edge top_edge(top_left, top_right); 1293 LayerQuad::Edge right_edge(top_right, bottom_right); 1294 1295 // Only apply anti-aliasing to edges not clipped by culling or scissoring. 1296 if (quad->IsTopEdge() && tile_rect.y() == quad->rect.y()) 1297 top_edge = device_layer_edges.top(); 1298 if (quad->IsLeftEdge() && tile_rect.x() == quad->rect.x()) 1299 left_edge = device_layer_edges.left(); 1300 if (quad->IsRightEdge() && tile_rect.right() == quad->rect.right()) 1301 right_edge = device_layer_edges.right(); 1302 if (quad->IsBottomEdge() && tile_rect.bottom() == quad->rect.bottom()) 1303 bottom_edge = device_layer_edges.bottom(); 1304 1305 float sign = gfx::QuadF(tile_rect).IsCounterClockwise() ? -1 : 1; 1306 bottom_edge.scale(sign); 1307 left_edge.scale(sign); 1308 top_edge.scale(sign); 1309 right_edge.scale(sign); 1310 1311 // Create device space quad. 1312 LayerQuad device_quad(left_edge, top_edge, right_edge, bottom_edge); 1313 1314 // Map device space quad to local space. device_transform has no 3d 1315 // component since it was flattened, so we don't need to project. We should 1316 // have already checked that the transform was uninvertible above. 1317 gfx::Transform inverse_device_transform(gfx::Transform::kSkipInitialization); 1318 bool did_invert = device_transform.GetInverse(&inverse_device_transform); 1319 DCHECK(did_invert); 1320 *local_quad = MathUtil::MapQuad( 1321 inverse_device_transform, device_quad.ToQuadF(), &clipped); 1322 // We should not DCHECK(!clipped) here, because anti-aliasing inflation may 1323 // cause device_quad to become clipped. To our knowledge this scenario does 1324 // not need to be handled differently than the unclipped case. 1325 1326 return true; 1327} 1328 1329void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame, 1330 const SolidColorDrawQuad* quad) { 1331 gfx::Rect tile_rect = quad->visible_rect; 1332 1333 SkColor color = quad->color; 1334 float opacity = quad->opacity(); 1335 float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity; 1336 1337 // Early out if alpha is small enough that quad doesn't contribute to output. 1338 if (alpha < std::numeric_limits<float>::epsilon() && 1339 quad->ShouldDrawWithBlending()) 1340 return; 1341 1342 gfx::Transform device_transform = 1343 frame->window_matrix * frame->projection_matrix * quad->quadTransform(); 1344 device_transform.FlattenTo2d(); 1345 if (!device_transform.IsInvertible()) 1346 return; 1347 1348 gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect)); 1349 float edge[24]; 1350 bool use_aa = 1351 settings_->allow_antialiasing && !quad->force_anti_aliasing_off && 1352 SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge); 1353 1354 SolidColorProgramUniforms uniforms; 1355 if (use_aa) 1356 SolidColorUniformLocation(GetSolidColorProgramAA(), &uniforms); 1357 else 1358 SolidColorUniformLocation(GetSolidColorProgram(), &uniforms); 1359 SetUseProgram(uniforms.program); 1360 1361 GLC(gl_, 1362 gl_->Uniform4f(uniforms.color_location, 1363 (SkColorGetR(color) * (1.0f / 255.0f)) * alpha, 1364 (SkColorGetG(color) * (1.0f / 255.0f)) * alpha, 1365 (SkColorGetB(color) * (1.0f / 255.0f)) * alpha, 1366 alpha)); 1367 if (use_aa) { 1368 float viewport[4] = {static_cast<float>(viewport_.x()), 1369 static_cast<float>(viewport_.y()), 1370 static_cast<float>(viewport_.width()), 1371 static_cast<float>(viewport_.height()), }; 1372 GLC(gl_, gl_->Uniform4fv(uniforms.viewport_location, 1, viewport)); 1373 GLC(gl_, gl_->Uniform3fv(uniforms.edge_location, 8, edge)); 1374 } 1375 1376 // Enable blending when the quad properties require it or if we decided 1377 // to use antialiasing. 1378 SetBlendEnabled(quad->ShouldDrawWithBlending() || use_aa); 1379 1380 // Normalize to tile_rect. 1381 local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height()); 1382 1383 SetShaderQuadF(local_quad, uniforms.quad_location); 1384 1385 // The transform and vertex data are used to figure out the extents that the 1386 // un-antialiased quad should have and which vertex this is and the float 1387 // quad passed in via uniform is the actual geometry that gets used to draw 1388 // it. This is why this centered rect is used and not the original quad_rect. 1389 gfx::RectF centered_rect( 1390 gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()), 1391 tile_rect.size()); 1392 DrawQuadGeometry( 1393 frame, quad->quadTransform(), centered_rect, uniforms.matrix_location); 1394} 1395 1396struct TileProgramUniforms { 1397 unsigned program; 1398 unsigned matrix_location; 1399 unsigned viewport_location; 1400 unsigned quad_location; 1401 unsigned edge_location; 1402 unsigned vertex_tex_transform_location; 1403 unsigned sampler_location; 1404 unsigned fragment_tex_transform_location; 1405 unsigned alpha_location; 1406}; 1407 1408template <class T> 1409static void TileUniformLocation(T program, TileProgramUniforms* uniforms) { 1410 uniforms->program = program->program(); 1411 uniforms->matrix_location = program->vertex_shader().matrix_location(); 1412 uniforms->viewport_location = program->vertex_shader().viewport_location(); 1413 uniforms->quad_location = program->vertex_shader().quad_location(); 1414 uniforms->edge_location = program->vertex_shader().edge_location(); 1415 uniforms->vertex_tex_transform_location = 1416 program->vertex_shader().vertex_tex_transform_location(); 1417 1418 uniforms->sampler_location = program->fragment_shader().sampler_location(); 1419 uniforms->alpha_location = program->fragment_shader().alpha_location(); 1420 uniforms->fragment_tex_transform_location = 1421 program->fragment_shader().fragment_tex_transform_location(); 1422} 1423 1424void GLRenderer::DrawTileQuad(const DrawingFrame* frame, 1425 const TileDrawQuad* quad) { 1426 DrawContentQuad(frame, quad, quad->resource_id); 1427} 1428 1429void GLRenderer::DrawContentQuad(const DrawingFrame* frame, 1430 const ContentDrawQuadBase* quad, 1431 ResourceProvider::ResourceId resource_id) { 1432 gfx::Rect tile_rect = quad->visible_rect; 1433 1434 gfx::RectF tex_coord_rect = MathUtil::ScaleRectProportional( 1435 quad->tex_coord_rect, quad->rect, tile_rect); 1436 float tex_to_geom_scale_x = quad->rect.width() / quad->tex_coord_rect.width(); 1437 float tex_to_geom_scale_y = 1438 quad->rect.height() / quad->tex_coord_rect.height(); 1439 1440 gfx::RectF clamp_geom_rect(tile_rect); 1441 gfx::RectF clamp_tex_rect(tex_coord_rect); 1442 // Clamp texture coordinates to avoid sampling outside the layer 1443 // by deflating the tile region half a texel or half a texel 1444 // minus epsilon for one pixel layers. The resulting clamp region 1445 // is mapped to the unit square by the vertex shader and mapped 1446 // back to normalized texture coordinates by the fragment shader 1447 // after being clamped to 0-1 range. 1448 float tex_clamp_x = 1449 std::min(0.5f, 0.5f * clamp_tex_rect.width() - kAntiAliasingEpsilon); 1450 float tex_clamp_y = 1451 std::min(0.5f, 0.5f * clamp_tex_rect.height() - kAntiAliasingEpsilon); 1452 float geom_clamp_x = 1453 std::min(tex_clamp_x * tex_to_geom_scale_x, 1454 0.5f * clamp_geom_rect.width() - kAntiAliasingEpsilon); 1455 float geom_clamp_y = 1456 std::min(tex_clamp_y * tex_to_geom_scale_y, 1457 0.5f * clamp_geom_rect.height() - kAntiAliasingEpsilon); 1458 clamp_geom_rect.Inset(geom_clamp_x, geom_clamp_y, geom_clamp_x, geom_clamp_y); 1459 clamp_tex_rect.Inset(tex_clamp_x, tex_clamp_y, tex_clamp_x, tex_clamp_y); 1460 1461 // Map clamping rectangle to unit square. 1462 float vertex_tex_translate_x = -clamp_geom_rect.x() / clamp_geom_rect.width(); 1463 float vertex_tex_translate_y = 1464 -clamp_geom_rect.y() / clamp_geom_rect.height(); 1465 float vertex_tex_scale_x = tile_rect.width() / clamp_geom_rect.width(); 1466 float vertex_tex_scale_y = tile_rect.height() / clamp_geom_rect.height(); 1467 1468 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 1469 gl_, &highp_threshold_cache_, highp_threshold_min_, quad->texture_size); 1470 1471 gfx::Transform device_transform = 1472 frame->window_matrix * frame->projection_matrix * quad->quadTransform(); 1473 device_transform.FlattenTo2d(); 1474 if (!device_transform.IsInvertible()) 1475 return; 1476 1477 gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect)); 1478 float edge[24]; 1479 bool use_aa = 1480 settings_->allow_antialiasing && 1481 SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge); 1482 1483 bool scaled = (tex_to_geom_scale_x != 1.f || tex_to_geom_scale_y != 1.f); 1484 GLenum filter = (use_aa || scaled || 1485 !quad->quadTransform().IsIdentityOrIntegerTranslation()) 1486 ? GL_LINEAR 1487 : GL_NEAREST; 1488 ResourceProvider::ScopedSamplerGL quad_resource_lock( 1489 resource_provider_, resource_id, filter); 1490 SamplerType sampler = 1491 SamplerTypeFromTextureTarget(quad_resource_lock.target()); 1492 1493 float fragment_tex_translate_x = clamp_tex_rect.x(); 1494 float fragment_tex_translate_y = clamp_tex_rect.y(); 1495 float fragment_tex_scale_x = clamp_tex_rect.width(); 1496 float fragment_tex_scale_y = clamp_tex_rect.height(); 1497 1498 // Map to normalized texture coordinates. 1499 if (sampler != SamplerType2DRect) { 1500 gfx::Size texture_size = quad->texture_size; 1501 DCHECK(!texture_size.IsEmpty()); 1502 fragment_tex_translate_x /= texture_size.width(); 1503 fragment_tex_translate_y /= texture_size.height(); 1504 fragment_tex_scale_x /= texture_size.width(); 1505 fragment_tex_scale_y /= texture_size.height(); 1506 } 1507 1508 TileProgramUniforms uniforms; 1509 if (use_aa) { 1510 if (quad->swizzle_contents) { 1511 TileUniformLocation(GetTileProgramSwizzleAA(tex_coord_precision, sampler), 1512 &uniforms); 1513 } else { 1514 TileUniformLocation(GetTileProgramAA(tex_coord_precision, sampler), 1515 &uniforms); 1516 } 1517 } else { 1518 if (quad->ShouldDrawWithBlending()) { 1519 if (quad->swizzle_contents) { 1520 TileUniformLocation(GetTileProgramSwizzle(tex_coord_precision, sampler), 1521 &uniforms); 1522 } else { 1523 TileUniformLocation(GetTileProgram(tex_coord_precision, sampler), 1524 &uniforms); 1525 } 1526 } else { 1527 if (quad->swizzle_contents) { 1528 TileUniformLocation( 1529 GetTileProgramSwizzleOpaque(tex_coord_precision, sampler), 1530 &uniforms); 1531 } else { 1532 TileUniformLocation(GetTileProgramOpaque(tex_coord_precision, sampler), 1533 &uniforms); 1534 } 1535 } 1536 } 1537 1538 SetUseProgram(uniforms.program); 1539 GLC(gl_, gl_->Uniform1i(uniforms.sampler_location, 0)); 1540 1541 if (use_aa) { 1542 float viewport[4] = {static_cast<float>(viewport_.x()), 1543 static_cast<float>(viewport_.y()), 1544 static_cast<float>(viewport_.width()), 1545 static_cast<float>(viewport_.height()), }; 1546 GLC(gl_, gl_->Uniform4fv(uniforms.viewport_location, 1, viewport)); 1547 GLC(gl_, gl_->Uniform3fv(uniforms.edge_location, 8, edge)); 1548 1549 GLC(gl_, 1550 gl_->Uniform4f(uniforms.vertex_tex_transform_location, 1551 vertex_tex_translate_x, 1552 vertex_tex_translate_y, 1553 vertex_tex_scale_x, 1554 vertex_tex_scale_y)); 1555 GLC(gl_, 1556 gl_->Uniform4f(uniforms.fragment_tex_transform_location, 1557 fragment_tex_translate_x, 1558 fragment_tex_translate_y, 1559 fragment_tex_scale_x, 1560 fragment_tex_scale_y)); 1561 } else { 1562 // Move fragment shader transform to vertex shader. We can do this while 1563 // still producing correct results as fragment_tex_transform_location 1564 // should always be non-negative when tiles are transformed in a way 1565 // that could result in sampling outside the layer. 1566 vertex_tex_scale_x *= fragment_tex_scale_x; 1567 vertex_tex_scale_y *= fragment_tex_scale_y; 1568 vertex_tex_translate_x *= fragment_tex_scale_x; 1569 vertex_tex_translate_y *= fragment_tex_scale_y; 1570 vertex_tex_translate_x += fragment_tex_translate_x; 1571 vertex_tex_translate_y += fragment_tex_translate_y; 1572 1573 GLC(gl_, 1574 gl_->Uniform4f(uniforms.vertex_tex_transform_location, 1575 vertex_tex_translate_x, 1576 vertex_tex_translate_y, 1577 vertex_tex_scale_x, 1578 vertex_tex_scale_y)); 1579 } 1580 1581 // Enable blending when the quad properties require it or if we decided 1582 // to use antialiasing. 1583 SetBlendEnabled(quad->ShouldDrawWithBlending() || use_aa); 1584 1585 // Normalize to tile_rect. 1586 local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height()); 1587 1588 SetShaderOpacity(quad->opacity(), uniforms.alpha_location); 1589 SetShaderQuadF(local_quad, uniforms.quad_location); 1590 1591 // The transform and vertex data are used to figure out the extents that the 1592 // un-antialiased quad should have and which vertex this is and the float 1593 // quad passed in via uniform is the actual geometry that gets used to draw 1594 // it. This is why this centered rect is used and not the original quad_rect. 1595 gfx::RectF centered_rect( 1596 gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()), 1597 tile_rect.size()); 1598 DrawQuadGeometry( 1599 frame, quad->quadTransform(), centered_rect, uniforms.matrix_location); 1600} 1601 1602void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame, 1603 const YUVVideoDrawQuad* quad) { 1604 SetBlendEnabled(quad->ShouldDrawWithBlending()); 1605 1606 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 1607 gl_, 1608 &highp_threshold_cache_, 1609 highp_threshold_min_, 1610 quad->shared_quad_state->visible_content_rect.bottom_right()); 1611 1612 bool use_alpha_plane = quad->a_plane_resource_id != 0; 1613 1614 ResourceProvider::ScopedSamplerGL y_plane_lock( 1615 resource_provider_, quad->y_plane_resource_id, GL_TEXTURE1, GL_LINEAR); 1616 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), y_plane_lock.target()); 1617 ResourceProvider::ScopedSamplerGL u_plane_lock( 1618 resource_provider_, quad->u_plane_resource_id, GL_TEXTURE2, GL_LINEAR); 1619 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), u_plane_lock.target()); 1620 ResourceProvider::ScopedSamplerGL v_plane_lock( 1621 resource_provider_, quad->v_plane_resource_id, GL_TEXTURE3, GL_LINEAR); 1622 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), v_plane_lock.target()); 1623 scoped_ptr<ResourceProvider::ScopedSamplerGL> a_plane_lock; 1624 if (use_alpha_plane) { 1625 a_plane_lock.reset(new ResourceProvider::ScopedSamplerGL( 1626 resource_provider_, quad->a_plane_resource_id, GL_TEXTURE4, GL_LINEAR)); 1627 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), a_plane_lock->target()); 1628 } 1629 1630 int tex_scale_location = -1; 1631 int matrix_location = -1; 1632 int y_texture_location = -1; 1633 int u_texture_location = -1; 1634 int v_texture_location = -1; 1635 int a_texture_location = -1; 1636 int yuv_matrix_location = -1; 1637 int yuv_adj_location = -1; 1638 int alpha_location = -1; 1639 if (use_alpha_plane) { 1640 const VideoYUVAProgram* program = GetVideoYUVAProgram(tex_coord_precision); 1641 DCHECK(program && (program->initialized() || IsContextLost())); 1642 SetUseProgram(program->program()); 1643 tex_scale_location = program->vertex_shader().tex_scale_location(); 1644 matrix_location = program->vertex_shader().matrix_location(); 1645 y_texture_location = program->fragment_shader().y_texture_location(); 1646 u_texture_location = program->fragment_shader().u_texture_location(); 1647 v_texture_location = program->fragment_shader().v_texture_location(); 1648 a_texture_location = program->fragment_shader().a_texture_location(); 1649 yuv_matrix_location = program->fragment_shader().yuv_matrix_location(); 1650 yuv_adj_location = program->fragment_shader().yuv_adj_location(); 1651 alpha_location = program->fragment_shader().alpha_location(); 1652 } else { 1653 const VideoYUVProgram* program = GetVideoYUVProgram(tex_coord_precision); 1654 DCHECK(program && (program->initialized() || IsContextLost())); 1655 SetUseProgram(program->program()); 1656 tex_scale_location = program->vertex_shader().tex_scale_location(); 1657 matrix_location = program->vertex_shader().matrix_location(); 1658 y_texture_location = program->fragment_shader().y_texture_location(); 1659 u_texture_location = program->fragment_shader().u_texture_location(); 1660 v_texture_location = program->fragment_shader().v_texture_location(); 1661 yuv_matrix_location = program->fragment_shader().yuv_matrix_location(); 1662 yuv_adj_location = program->fragment_shader().yuv_adj_location(); 1663 alpha_location = program->fragment_shader().alpha_location(); 1664 } 1665 1666 GLC(gl_, 1667 gl_->Uniform2f(tex_scale_location, 1668 quad->tex_scale.width(), 1669 quad->tex_scale.height())); 1670 GLC(gl_, gl_->Uniform1i(y_texture_location, 1)); 1671 GLC(gl_, gl_->Uniform1i(u_texture_location, 2)); 1672 GLC(gl_, gl_->Uniform1i(v_texture_location, 3)); 1673 if (use_alpha_plane) 1674 GLC(gl_, gl_->Uniform1i(a_texture_location, 4)); 1675 1676 // These values are magic numbers that are used in the transformation from YUV 1677 // to RGB color values. They are taken from the following webpage: 1678 // http://www.fourcc.org/fccyvrgb.php 1679 float yuv_to_rgb[9] = {1.164f, 1.164f, 1.164f, 0.0f, -.391f, 1680 2.018f, 1.596f, -.813f, 0.0f, }; 1681 GLC(gl_, gl_->UniformMatrix3fv(yuv_matrix_location, 1, 0, yuv_to_rgb)); 1682 1683 // These values map to 16, 128, and 128 respectively, and are computed 1684 // as a fraction over 256 (e.g. 16 / 256 = 0.0625). 1685 // They are used in the YUV to RGBA conversion formula: 1686 // Y - 16 : Gives 16 values of head and footroom for overshooting 1687 // U - 128 : Turns unsigned U into signed U [-128,127] 1688 // V - 128 : Turns unsigned V into signed V [-128,127] 1689 float yuv_adjust[3] = {-0.0625f, -0.5f, -0.5f, }; 1690 GLC(gl_, gl_->Uniform3fv(yuv_adj_location, 1, yuv_adjust)); 1691 1692 SetShaderOpacity(quad->opacity(), alpha_location); 1693 DrawQuadGeometry(frame, quad->quadTransform(), quad->rect, matrix_location); 1694} 1695 1696void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame, 1697 const StreamVideoDrawQuad* quad) { 1698 SetBlendEnabled(quad->ShouldDrawWithBlending()); 1699 1700 static float gl_matrix[16]; 1701 1702 DCHECK(capabilities_.using_egl_image); 1703 1704 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 1705 gl_, 1706 &highp_threshold_cache_, 1707 highp_threshold_min_, 1708 quad->shared_quad_state->visible_content_rect.bottom_right()); 1709 1710 const VideoStreamTextureProgram* program = 1711 GetVideoStreamTextureProgram(tex_coord_precision); 1712 SetUseProgram(program->program()); 1713 1714 ToGLMatrix(&gl_matrix[0], quad->matrix); 1715 GLC(gl_, 1716 gl_->UniformMatrix4fv( 1717 program->vertex_shader().tex_matrix_location(), 1, false, gl_matrix)); 1718 1719 ResourceProvider::ScopedReadLockGL lock(resource_provider_, 1720 quad->resource_id); 1721 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_)); 1722 GLC(gl_, gl_->BindTexture(GL_TEXTURE_EXTERNAL_OES, lock.texture_id())); 1723 1724 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1725 1726 SetShaderOpacity(quad->opacity(), 1727 program->fragment_shader().alpha_location()); 1728 DrawQuadGeometry(frame, 1729 quad->quadTransform(), 1730 quad->rect, 1731 program->vertex_shader().matrix_location()); 1732} 1733 1734void GLRenderer::DrawPictureQuad(const DrawingFrame* frame, 1735 const PictureDrawQuad* quad) { 1736 if (on_demand_tile_raster_bitmap_.width() != quad->texture_size.width() || 1737 on_demand_tile_raster_bitmap_.height() != quad->texture_size.height()) { 1738 on_demand_tile_raster_bitmap_.setConfig(SkBitmap::kARGB_8888_Config, 1739 quad->texture_size.width(), 1740 quad->texture_size.height()); 1741 on_demand_tile_raster_bitmap_.allocPixels(); 1742 1743 if (on_demand_tile_raster_resource_id_) 1744 resource_provider_->DeleteResource(on_demand_tile_raster_resource_id_); 1745 1746 on_demand_tile_raster_resource_id_ = 1747 resource_provider_->CreateGLTexture(quad->texture_size, 1748 GL_TEXTURE_2D, 1749 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM, 1750 GL_CLAMP_TO_EDGE, 1751 ResourceProvider::TextureUsageAny, 1752 quad->texture_format); 1753 } 1754 1755 // Create and run on-demand raster task for tile. 1756 scoped_refptr<internal::Task> on_demand_raster_task( 1757 new OnDemandRasterTaskImpl(quad->picture_pile, 1758 &on_demand_tile_raster_bitmap_, 1759 quad->content_rect, 1760 quad->contents_scale)); 1761 RunOnDemandRasterTask(on_demand_raster_task.get()); 1762 1763 uint8_t* bitmap_pixels = NULL; 1764 SkBitmap on_demand_tile_raster_bitmap_dest; 1765 SkBitmap::Config config = SkBitmapConfig(quad->texture_format); 1766 if (on_demand_tile_raster_bitmap_.getConfig() != config) { 1767 on_demand_tile_raster_bitmap_.copyTo(&on_demand_tile_raster_bitmap_dest, 1768 config); 1769 // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the 1770 // bitmap data. This check will be removed once crbug.com/293728 is fixed. 1771 CHECK_EQ(0u, on_demand_tile_raster_bitmap_dest.rowBytes() % 4); 1772 bitmap_pixels = reinterpret_cast<uint8_t*>( 1773 on_demand_tile_raster_bitmap_dest.getPixels()); 1774 } else { 1775 bitmap_pixels = 1776 reinterpret_cast<uint8_t*>(on_demand_tile_raster_bitmap_.getPixels()); 1777 } 1778 1779 resource_provider_->SetPixels(on_demand_tile_raster_resource_id_, 1780 bitmap_pixels, 1781 gfx::Rect(quad->texture_size), 1782 gfx::Rect(quad->texture_size), 1783 gfx::Vector2d()); 1784 1785 DrawContentQuad(frame, quad, on_demand_tile_raster_resource_id_); 1786} 1787 1788struct TextureProgramBinding { 1789 template <class Program> 1790 void Set(Program* program) { 1791 DCHECK(program); 1792 program_id = program->program(); 1793 sampler_location = program->fragment_shader().sampler_location(); 1794 matrix_location = program->vertex_shader().matrix_location(); 1795 background_color_location = 1796 program->fragment_shader().background_color_location(); 1797 } 1798 int program_id; 1799 int sampler_location; 1800 int matrix_location; 1801 int background_color_location; 1802}; 1803 1804struct TexTransformTextureProgramBinding : TextureProgramBinding { 1805 template <class Program> 1806 void Set(Program* program) { 1807 TextureProgramBinding::Set(program); 1808 tex_transform_location = program->vertex_shader().tex_transform_location(); 1809 vertex_opacity_location = 1810 program->vertex_shader().vertex_opacity_location(); 1811 } 1812 int tex_transform_location; 1813 int vertex_opacity_location; 1814}; 1815 1816void GLRenderer::FlushTextureQuadCache() { 1817 // Check to see if we have anything to draw. 1818 if (draw_cache_.program_id == 0) 1819 return; 1820 1821 // Set the correct blending mode. 1822 SetBlendEnabled(draw_cache_.needs_blending); 1823 1824 // Bind the program to the GL state. 1825 SetUseProgram(draw_cache_.program_id); 1826 1827 // Bind the correct texture sampler location. 1828 GLC(gl_, gl_->Uniform1i(draw_cache_.sampler_location, 0)); 1829 1830 // Assume the current active textures is 0. 1831 ResourceProvider::ScopedReadLockGL locked_quad(resource_provider_, 1832 draw_cache_.resource_id); 1833 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_)); 1834 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, locked_quad.texture_id())); 1835 1836 COMPILE_ASSERT(sizeof(Float4) == 4 * sizeof(float), // NOLINT(runtime/sizeof) 1837 struct_is_densely_packed); 1838 COMPILE_ASSERT( 1839 sizeof(Float16) == 16 * sizeof(float), // NOLINT(runtime/sizeof) 1840 struct_is_densely_packed); 1841 1842 // Upload the tranforms for both points and uvs. 1843 GLC(gl_, 1844 gl_->UniformMatrix4fv( 1845 static_cast<int>(draw_cache_.matrix_location), 1846 static_cast<int>(draw_cache_.matrix_data.size()), 1847 false, 1848 reinterpret_cast<float*>(&draw_cache_.matrix_data.front()))); 1849 GLC(gl_, 1850 gl_->Uniform4fv( 1851 static_cast<int>(draw_cache_.uv_xform_location), 1852 static_cast<int>(draw_cache_.uv_xform_data.size()), 1853 reinterpret_cast<float*>(&draw_cache_.uv_xform_data.front()))); 1854 1855 if (draw_cache_.background_color != SK_ColorTRANSPARENT) { 1856 Float4 background_color = PremultipliedColor(draw_cache_.background_color); 1857 GLC(gl_, 1858 gl_->Uniform4fv( 1859 draw_cache_.background_color_location, 1, background_color.data)); 1860 } 1861 1862 GLC(gl_, 1863 gl_->Uniform1fv( 1864 static_cast<int>(draw_cache_.vertex_opacity_location), 1865 static_cast<int>(draw_cache_.vertex_opacity_data.size()), 1866 static_cast<float*>(&draw_cache_.vertex_opacity_data.front()))); 1867 1868 // Draw the quads! 1869 GLC(gl_, 1870 gl_->DrawElements(GL_TRIANGLES, 1871 6 * draw_cache_.matrix_data.size(), 1872 GL_UNSIGNED_SHORT, 1873 0)); 1874 1875 // Clear the cache. 1876 draw_cache_.program_id = 0; 1877 draw_cache_.uv_xform_data.resize(0); 1878 draw_cache_.vertex_opacity_data.resize(0); 1879 draw_cache_.matrix_data.resize(0); 1880} 1881 1882void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame, 1883 const TextureDrawQuad* quad) { 1884 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 1885 gl_, 1886 &highp_threshold_cache_, 1887 highp_threshold_min_, 1888 quad->shared_quad_state->visible_content_rect.bottom_right()); 1889 1890 // Choose the correct texture program binding 1891 TexTransformTextureProgramBinding binding; 1892 if (quad->premultiplied_alpha) { 1893 if (quad->background_color == SK_ColorTRANSPARENT) { 1894 binding.Set(GetTextureProgram(tex_coord_precision)); 1895 } else { 1896 binding.Set(GetTextureBackgroundProgram(tex_coord_precision)); 1897 } 1898 } else { 1899 if (quad->background_color == SK_ColorTRANSPARENT) { 1900 binding.Set(GetNonPremultipliedTextureProgram(tex_coord_precision)); 1901 } else { 1902 binding.Set( 1903 GetNonPremultipliedTextureBackgroundProgram(tex_coord_precision)); 1904 } 1905 } 1906 1907 int resource_id = quad->resource_id; 1908 1909 if (draw_cache_.program_id != binding.program_id || 1910 draw_cache_.resource_id != resource_id || 1911 draw_cache_.needs_blending != quad->ShouldDrawWithBlending() || 1912 draw_cache_.background_color != quad->background_color || 1913 draw_cache_.matrix_data.size() >= 8) { 1914 FlushTextureQuadCache(); 1915 draw_cache_.program_id = binding.program_id; 1916 draw_cache_.resource_id = resource_id; 1917 draw_cache_.needs_blending = quad->ShouldDrawWithBlending(); 1918 draw_cache_.background_color = quad->background_color; 1919 1920 draw_cache_.uv_xform_location = binding.tex_transform_location; 1921 draw_cache_.background_color_location = binding.background_color_location; 1922 draw_cache_.vertex_opacity_location = binding.vertex_opacity_location; 1923 draw_cache_.matrix_location = binding.matrix_location; 1924 draw_cache_.sampler_location = binding.sampler_location; 1925 } 1926 1927 // Generate the uv-transform 1928 draw_cache_.uv_xform_data.push_back(UVTransform(quad)); 1929 1930 // Generate the vertex opacity 1931 const float opacity = quad->opacity(); 1932 draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[0] * opacity); 1933 draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[1] * opacity); 1934 draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[2] * opacity); 1935 draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[3] * opacity); 1936 1937 // Generate the transform matrix 1938 gfx::Transform quad_rect_matrix; 1939 QuadRectTransform(&quad_rect_matrix, quad->quadTransform(), quad->rect); 1940 quad_rect_matrix = frame->projection_matrix * quad_rect_matrix; 1941 1942 Float16 m; 1943 quad_rect_matrix.matrix().asColMajorf(m.data); 1944 draw_cache_.matrix_data.push_back(m); 1945} 1946 1947void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame* frame, 1948 const IOSurfaceDrawQuad* quad) { 1949 SetBlendEnabled(quad->ShouldDrawWithBlending()); 1950 1951 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 1952 gl_, 1953 &highp_threshold_cache_, 1954 highp_threshold_min_, 1955 quad->shared_quad_state->visible_content_rect.bottom_right()); 1956 1957 TexTransformTextureProgramBinding binding; 1958 binding.Set(GetTextureIOSurfaceProgram(tex_coord_precision)); 1959 1960 SetUseProgram(binding.program_id); 1961 GLC(gl_, gl_->Uniform1i(binding.sampler_location, 0)); 1962 if (quad->orientation == IOSurfaceDrawQuad::FLIPPED) { 1963 GLC(gl_, 1964 gl_->Uniform4f(binding.tex_transform_location, 1965 0, 1966 quad->io_surface_size.height(), 1967 quad->io_surface_size.width(), 1968 quad->io_surface_size.height() * -1.0f)); 1969 } else { 1970 GLC(gl_, 1971 gl_->Uniform4f(binding.tex_transform_location, 1972 0, 1973 0, 1974 quad->io_surface_size.width(), 1975 quad->io_surface_size.height())); 1976 } 1977 1978 const float vertex_opacity[] = {quad->opacity(), quad->opacity(), 1979 quad->opacity(), quad->opacity()}; 1980 GLC(gl_, gl_->Uniform1fv(binding.vertex_opacity_location, 4, vertex_opacity)); 1981 1982 ResourceProvider::ScopedReadLockGL lock(resource_provider_, 1983 quad->io_surface_resource_id); 1984 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_)); 1985 GLC(gl_, gl_->BindTexture(GL_TEXTURE_RECTANGLE_ARB, lock.texture_id())); 1986 1987 DrawQuadGeometry( 1988 frame, quad->quadTransform(), quad->rect, binding.matrix_location); 1989 1990 GLC(gl_, gl_->BindTexture(GL_TEXTURE_RECTANGLE_ARB, 0)); 1991} 1992 1993void GLRenderer::FinishDrawingFrame(DrawingFrame* frame) { 1994 current_framebuffer_lock_.reset(); 1995 swap_buffer_rect_.Union(gfx::ToEnclosingRect(frame->root_damage_rect)); 1996 1997 GLC(gl_, gl_->Disable(GL_BLEND)); 1998 blend_shadow_ = false; 1999} 2000 2001void GLRenderer::FinishDrawingQuadList() { FlushTextureQuadCache(); } 2002 2003bool GLRenderer::FlippedFramebuffer() const { return true; } 2004 2005void GLRenderer::EnsureScissorTestEnabled() { 2006 if (is_scissor_enabled_) 2007 return; 2008 2009 FlushTextureQuadCache(); 2010 GLC(gl_, gl_->Enable(GL_SCISSOR_TEST)); 2011 is_scissor_enabled_ = true; 2012} 2013 2014void GLRenderer::EnsureScissorTestDisabled() { 2015 if (!is_scissor_enabled_) 2016 return; 2017 2018 FlushTextureQuadCache(); 2019 GLC(gl_, gl_->Disable(GL_SCISSOR_TEST)); 2020 is_scissor_enabled_ = false; 2021} 2022 2023void GLRenderer::CopyCurrentRenderPassToBitmap( 2024 DrawingFrame* frame, 2025 scoped_ptr<CopyOutputRequest> request) { 2026 gfx::Rect copy_rect = frame->current_render_pass->output_rect; 2027 if (request->has_area()) 2028 copy_rect.Intersect(request->area()); 2029 GetFramebufferPixelsAsync(copy_rect, request.Pass()); 2030} 2031 2032void GLRenderer::ToGLMatrix(float* gl_matrix, const gfx::Transform& transform) { 2033 transform.matrix().asColMajorf(gl_matrix); 2034} 2035 2036void GLRenderer::SetShaderQuadF(const gfx::QuadF& quad, int quad_location) { 2037 if (quad_location == -1) 2038 return; 2039 2040 float gl_quad[8]; 2041 gl_quad[0] = quad.p1().x(); 2042 gl_quad[1] = quad.p1().y(); 2043 gl_quad[2] = quad.p2().x(); 2044 gl_quad[3] = quad.p2().y(); 2045 gl_quad[4] = quad.p3().x(); 2046 gl_quad[5] = quad.p3().y(); 2047 gl_quad[6] = quad.p4().x(); 2048 gl_quad[7] = quad.p4().y(); 2049 GLC(gl_, gl_->Uniform2fv(quad_location, 4, gl_quad)); 2050} 2051 2052void GLRenderer::SetShaderOpacity(float opacity, int alpha_location) { 2053 if (alpha_location != -1) 2054 GLC(gl_, gl_->Uniform1f(alpha_location, opacity)); 2055} 2056 2057void GLRenderer::SetStencilEnabled(bool enabled) { 2058 if (enabled == stencil_shadow_) 2059 return; 2060 2061 if (enabled) 2062 GLC(gl_, gl_->Enable(GL_STENCIL_TEST)); 2063 else 2064 GLC(gl_, gl_->Disable(GL_STENCIL_TEST)); 2065 stencil_shadow_ = enabled; 2066} 2067 2068void GLRenderer::SetBlendEnabled(bool enabled) { 2069 if (enabled == blend_shadow_) 2070 return; 2071 2072 if (enabled) 2073 GLC(gl_, gl_->Enable(GL_BLEND)); 2074 else 2075 GLC(gl_, gl_->Disable(GL_BLEND)); 2076 blend_shadow_ = enabled; 2077} 2078 2079void GLRenderer::SetUseProgram(unsigned program) { 2080 if (program == program_shadow_) 2081 return; 2082 gl_->UseProgram(program); 2083 program_shadow_ = program; 2084} 2085 2086void GLRenderer::DrawQuadGeometry(const DrawingFrame* frame, 2087 const gfx::Transform& draw_transform, 2088 const gfx::RectF& quad_rect, 2089 int matrix_location) { 2090 gfx::Transform quad_rect_matrix; 2091 QuadRectTransform(&quad_rect_matrix, draw_transform, quad_rect); 2092 static float gl_matrix[16]; 2093 ToGLMatrix(&gl_matrix[0], frame->projection_matrix * quad_rect_matrix); 2094 GLC(gl_, gl_->UniformMatrix4fv(matrix_location, 1, false, &gl_matrix[0])); 2095 2096 GLC(gl_, gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0)); 2097} 2098 2099void GLRenderer::CopyTextureToFramebuffer(const DrawingFrame* frame, 2100 int texture_id, 2101 const gfx::Rect& rect, 2102 const gfx::Transform& draw_matrix, 2103 bool flip_vertically) { 2104 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 2105 gl_, &highp_threshold_cache_, highp_threshold_min_, rect.bottom_right()); 2106 2107 const RenderPassProgram* program = GetRenderPassProgram(tex_coord_precision); 2108 SetUseProgram(program->program()); 2109 2110 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 2111 2112 if (flip_vertically) { 2113 GLC(gl_, 2114 gl_->Uniform4f(program->vertex_shader().tex_transform_location(), 2115 0.f, 2116 1.f, 2117 1.f, 2118 -1.f)); 2119 } else { 2120 GLC(gl_, 2121 gl_->Uniform4f(program->vertex_shader().tex_transform_location(), 2122 0.f, 2123 0.f, 2124 1.f, 2125 1.f)); 2126 } 2127 2128 SetShaderOpacity(1.f, program->fragment_shader().alpha_location()); 2129 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_)); 2130 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, texture_id)); 2131 DrawQuadGeometry( 2132 frame, draw_matrix, rect, program->vertex_shader().matrix_location()); 2133} 2134 2135void GLRenderer::Finish() { 2136 TRACE_EVENT0("cc", "GLRenderer::Finish"); 2137 GLC(gl_, gl_->Finish()); 2138} 2139 2140void GLRenderer::SwapBuffers(const CompositorFrameMetadata& metadata) { 2141 DCHECK(!is_backbuffer_discarded_); 2142 2143 TRACE_EVENT0("cc,benchmark", "GLRenderer::SwapBuffers"); 2144 // We're done! Time to swapbuffers! 2145 2146 gfx::Size surface_size = output_surface_->SurfaceSize(); 2147 2148 CompositorFrame compositor_frame; 2149 compositor_frame.metadata = metadata; 2150 compositor_frame.gl_frame_data = make_scoped_ptr(new GLFrameData); 2151 compositor_frame.gl_frame_data->size = surface_size; 2152 if (capabilities_.using_partial_swap) { 2153 // If supported, we can save significant bandwidth by only swapping the 2154 // damaged/scissored region (clamped to the viewport). 2155 swap_buffer_rect_.Intersect(gfx::Rect(surface_size)); 2156 int flipped_y_pos_of_rect_bottom = surface_size.height() - 2157 swap_buffer_rect_.y() - 2158 swap_buffer_rect_.height(); 2159 compositor_frame.gl_frame_data->sub_buffer_rect = 2160 gfx::Rect(swap_buffer_rect_.x(), 2161 flipped_y_pos_of_rect_bottom, 2162 swap_buffer_rect_.width(), 2163 swap_buffer_rect_.height()); 2164 } else { 2165 compositor_frame.gl_frame_data->sub_buffer_rect = 2166 gfx::Rect(output_surface_->SurfaceSize()); 2167 } 2168 output_surface_->SwapBuffers(&compositor_frame); 2169 2170 swap_buffer_rect_ = gfx::Rect(); 2171 2172 // We don't have real fences, so we mark read fences as passed 2173 // assuming a double-buffered GPU pipeline. A texture can be 2174 // written to after one full frame has past since it was last read. 2175 if (last_swap_fence_.get()) 2176 static_cast<SimpleSwapFence*>(last_swap_fence_.get())->SetHasPassed(); 2177 last_swap_fence_ = resource_provider_->GetReadLockFence(); 2178 resource_provider_->SetReadLockFence(new SimpleSwapFence()); 2179} 2180 2181void GLRenderer::EnforceMemoryPolicy() { 2182 if (!visible_) { 2183 TRACE_EVENT0("cc", "GLRenderer::EnforceMemoryPolicy dropping resources"); 2184 ReleaseRenderPassTextures(); 2185 DiscardBackbuffer(); 2186 resource_provider_->ReleaseCachedData(); 2187 GLC(gl_, gl_->Flush()); 2188 } 2189} 2190 2191void GLRenderer::DiscardBackbuffer() { 2192 if (is_backbuffer_discarded_) 2193 return; 2194 2195 output_surface_->DiscardBackbuffer(); 2196 2197 is_backbuffer_discarded_ = true; 2198 2199 // Damage tracker needs a full reset every time framebuffer is discarded. 2200 client_->SetFullRootLayerDamage(); 2201} 2202 2203void GLRenderer::EnsureBackbuffer() { 2204 if (!is_backbuffer_discarded_) 2205 return; 2206 2207 output_surface_->EnsureBackbuffer(); 2208 is_backbuffer_discarded_ = false; 2209} 2210 2211void GLRenderer::GetFramebufferPixels(void* pixels, const gfx::Rect& rect) { 2212 if (!pixels || rect.IsEmpty()) 2213 return; 2214 2215 // This function assumes that it is reading the root frame buffer. 2216 DCHECK(!current_framebuffer_lock_); 2217 2218 scoped_ptr<PendingAsyncReadPixels> pending_read(new PendingAsyncReadPixels); 2219 pending_async_read_pixels_.insert(pending_async_read_pixels_.begin(), 2220 pending_read.Pass()); 2221 2222 // This is a syncronous call since the callback is null. 2223 gfx::Rect window_rect = MoveFromDrawToWindowSpace(rect); 2224 DoGetFramebufferPixels(static_cast<uint8*>(pixels), 2225 window_rect, 2226 AsyncGetFramebufferPixelsCleanupCallback()); 2227} 2228 2229void GLRenderer::GetFramebufferPixelsAsync( 2230 const gfx::Rect& rect, 2231 scoped_ptr<CopyOutputRequest> request) { 2232 DCHECK(!request->IsEmpty()); 2233 if (request->IsEmpty()) 2234 return; 2235 if (rect.IsEmpty()) 2236 return; 2237 2238 gfx::Rect window_rect = MoveFromDrawToWindowSpace(rect); 2239 2240 if (!request->force_bitmap_result()) { 2241 bool own_mailbox = !request->has_texture_mailbox(); 2242 2243 GLuint texture_id = 0; 2244 gl_->GenTextures(1, &texture_id); 2245 2246 gpu::Mailbox mailbox; 2247 if (own_mailbox) { 2248 GLC(gl_, gl_->GenMailboxCHROMIUM(mailbox.name)); 2249 } else { 2250 mailbox = request->texture_mailbox().mailbox(); 2251 DCHECK_EQ(static_cast<unsigned>(GL_TEXTURE_2D), 2252 request->texture_mailbox().target()); 2253 DCHECK(!mailbox.IsZero()); 2254 unsigned incoming_sync_point = request->texture_mailbox().sync_point(); 2255 if (incoming_sync_point) 2256 GLC(gl_, gl_->WaitSyncPointCHROMIUM(incoming_sync_point)); 2257 } 2258 2259 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, texture_id)); 2260 if (own_mailbox) { 2261 GLC(gl_, 2262 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 2263 GLC(gl_, 2264 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 2265 GLC(gl_, 2266 gl_->TexParameteri( 2267 GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 2268 GLC(gl_, 2269 gl_->TexParameteri( 2270 GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 2271 GLC(gl_, gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name)); 2272 } else { 2273 GLC(gl_, gl_->ConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name)); 2274 } 2275 GetFramebufferTexture(texture_id, RGBA_8888, window_rect); 2276 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, 0)); 2277 2278 unsigned sync_point = gl_->InsertSyncPointCHROMIUM(); 2279 TextureMailbox texture_mailbox(mailbox, GL_TEXTURE_2D, sync_point); 2280 2281 scoped_ptr<SingleReleaseCallback> release_callback; 2282 if (own_mailbox) { 2283 release_callback = texture_mailbox_deleter_->GetReleaseCallback( 2284 output_surface_->context_provider(), texture_id); 2285 } else { 2286 gl_->DeleteTextures(1, &texture_id); 2287 } 2288 2289 request->SendTextureResult( 2290 window_rect.size(), texture_mailbox, release_callback.Pass()); 2291 return; 2292 } 2293 2294 DCHECK(request->force_bitmap_result()); 2295 2296 scoped_ptr<SkBitmap> bitmap(new SkBitmap); 2297 bitmap->setConfig( 2298 SkBitmap::kARGB_8888_Config, window_rect.width(), window_rect.height()); 2299 bitmap->allocPixels(); 2300 2301 scoped_ptr<SkAutoLockPixels> lock(new SkAutoLockPixels(*bitmap)); 2302 2303 // Save a pointer to the pixels, the bitmap is owned by the cleanup_callback. 2304 uint8* pixels = static_cast<uint8*>(bitmap->getPixels()); 2305 2306 AsyncGetFramebufferPixelsCleanupCallback cleanup_callback = 2307 base::Bind(&GLRenderer::PassOnSkBitmap, 2308 base::Unretained(this), 2309 base::Passed(&bitmap), 2310 base::Passed(&lock)); 2311 2312 scoped_ptr<PendingAsyncReadPixels> pending_read(new PendingAsyncReadPixels); 2313 pending_read->copy_request = request.Pass(); 2314 pending_async_read_pixels_.insert(pending_async_read_pixels_.begin(), 2315 pending_read.Pass()); 2316 2317 // This is an asyncronous call since the callback is not null. 2318 DoGetFramebufferPixels(pixels, window_rect, cleanup_callback); 2319} 2320 2321void GLRenderer::DoGetFramebufferPixels( 2322 uint8* dest_pixels, 2323 const gfx::Rect& window_rect, 2324 const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback) { 2325 DCHECK_GE(window_rect.x(), 0); 2326 DCHECK_GE(window_rect.y(), 0); 2327 DCHECK_LE(window_rect.right(), current_surface_size_.width()); 2328 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); 2329 2330 bool is_async = !cleanup_callback.is_null(); 2331 2332 bool do_workaround = NeedsIOSurfaceReadbackWorkaround(); 2333 2334 unsigned temporary_texture = 0; 2335 unsigned temporary_fbo = 0; 2336 2337 if (do_workaround) { 2338 // On Mac OS X, calling glReadPixels() against an FBO whose color attachment 2339 // is an IOSurface-backed texture causes corruption of future glReadPixels() 2340 // calls, even those on different OpenGL contexts. It is believed that this 2341 // is the root cause of top crasher 2342 // http://crbug.com/99393. <rdar://problem/10949687> 2343 2344 gl_->GenTextures(1, &temporary_texture); 2345 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, temporary_texture)); 2346 GLC(gl_, 2347 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 2348 GLC(gl_, 2349 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 2350 GLC(gl_, 2351 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 2352 GLC(gl_, 2353 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 2354 // Copy the contents of the current (IOSurface-backed) framebuffer into a 2355 // temporary texture. 2356 GetFramebufferTexture( 2357 temporary_texture, RGBA_8888, gfx::Rect(current_surface_size_)); 2358 gl_->GenFramebuffers(1, &temporary_fbo); 2359 // Attach this texture to an FBO, and perform the readback from that FBO. 2360 GLC(gl_, gl_->BindFramebuffer(GL_FRAMEBUFFER, temporary_fbo)); 2361 GLC(gl_, 2362 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, 2363 GL_COLOR_ATTACHMENT0, 2364 GL_TEXTURE_2D, 2365 temporary_texture, 2366 0)); 2367 2368 DCHECK_EQ(static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE), 2369 gl_->CheckFramebufferStatus(GL_FRAMEBUFFER)); 2370 } 2371 2372 GLuint buffer = 0; 2373 gl_->GenBuffers(1, &buffer); 2374 GLC(gl_, gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, buffer)); 2375 GLC(gl_, 2376 gl_->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 2377 4 * window_rect.size().GetArea(), 2378 NULL, 2379 GL_STREAM_READ)); 2380 2381 GLuint query = 0; 2382 if (is_async) { 2383 gl_->GenQueriesEXT(1, &query); 2384 GLC(gl_, gl_->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, query)); 2385 } 2386 2387 GLC(gl_, 2388 gl_->ReadPixels(window_rect.x(), 2389 window_rect.y(), 2390 window_rect.width(), 2391 window_rect.height(), 2392 GL_RGBA, 2393 GL_UNSIGNED_BYTE, 2394 NULL)); 2395 2396 GLC(gl_, gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0)); 2397 2398 if (do_workaround) { 2399 // Clean up. 2400 GLC(gl_, gl_->BindFramebuffer(GL_FRAMEBUFFER, 0)); 2401 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, 0)); 2402 GLC(gl_, gl_->DeleteFramebuffers(1, &temporary_fbo)); 2403 GLC(gl_, gl_->DeleteTextures(1, &temporary_texture)); 2404 } 2405 2406 base::Closure finished_callback = base::Bind(&GLRenderer::FinishedReadback, 2407 base::Unretained(this), 2408 cleanup_callback, 2409 buffer, 2410 query, 2411 dest_pixels, 2412 window_rect.size()); 2413 // Save the finished_callback so it can be cancelled. 2414 pending_async_read_pixels_.front()->finished_read_pixels_callback.Reset( 2415 finished_callback); 2416 base::Closure cancelable_callback = 2417 pending_async_read_pixels_.front()-> 2418 finished_read_pixels_callback.callback(); 2419 2420 // Save the buffer to verify the callbacks happen in the expected order. 2421 pending_async_read_pixels_.front()->buffer = buffer; 2422 2423 if (is_async) { 2424 GLC(gl_, gl_->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM)); 2425 context_support_->SignalQuery(query, cancelable_callback); 2426 } else { 2427 resource_provider_->Finish(); 2428 finished_callback.Run(); 2429 } 2430 2431 EnforceMemoryPolicy(); 2432} 2433 2434void GLRenderer::FinishedReadback( 2435 const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback, 2436 unsigned source_buffer, 2437 unsigned query, 2438 uint8* dest_pixels, 2439 const gfx::Size& size) { 2440 DCHECK(!pending_async_read_pixels_.empty()); 2441 2442 if (query != 0) { 2443 GLC(gl_, gl_->DeleteQueriesEXT(1, &query)); 2444 } 2445 2446 PendingAsyncReadPixels* current_read = pending_async_read_pixels_.back(); 2447 // Make sure we service the readbacks in order. 2448 DCHECK_EQ(source_buffer, current_read->buffer); 2449 2450 uint8* src_pixels = NULL; 2451 2452 if (source_buffer != 0) { 2453 GLC(gl_, 2454 gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, source_buffer)); 2455 src_pixels = static_cast<uint8*>(gl_->MapBufferCHROMIUM( 2456 GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY)); 2457 2458 if (src_pixels) { 2459 size_t row_bytes = size.width() * 4; 2460 int num_rows = size.height(); 2461 size_t total_bytes = num_rows * row_bytes; 2462 for (size_t dest_y = 0; dest_y < total_bytes; dest_y += row_bytes) { 2463 // Flip Y axis. 2464 size_t src_y = total_bytes - dest_y - row_bytes; 2465 // Swizzle OpenGL -> Skia byte order. 2466 for (size_t x = 0; x < row_bytes; x += 4) { 2467 dest_pixels[dest_y + x + SK_R32_SHIFT / 8] = 2468 src_pixels[src_y + x + 0]; 2469 dest_pixels[dest_y + x + SK_G32_SHIFT / 8] = 2470 src_pixels[src_y + x + 1]; 2471 dest_pixels[dest_y + x + SK_B32_SHIFT / 8] = 2472 src_pixels[src_y + x + 2]; 2473 dest_pixels[dest_y + x + SK_A32_SHIFT / 8] = 2474 src_pixels[src_y + x + 3]; 2475 } 2476 } 2477 2478 GLC(gl_, 2479 gl_->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM)); 2480 } 2481 GLC(gl_, gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0)); 2482 GLC(gl_, gl_->DeleteBuffers(1, &source_buffer)); 2483 } 2484 2485 // TODO(danakj): This can go away when synchronous readback is no more and its 2486 // contents can just move here. 2487 if (!cleanup_callback.is_null()) 2488 cleanup_callback.Run(current_read->copy_request.Pass(), src_pixels != NULL); 2489 2490 pending_async_read_pixels_.pop_back(); 2491} 2492 2493void GLRenderer::PassOnSkBitmap(scoped_ptr<SkBitmap> bitmap, 2494 scoped_ptr<SkAutoLockPixels> lock, 2495 scoped_ptr<CopyOutputRequest> request, 2496 bool success) { 2497 DCHECK(request->force_bitmap_result()); 2498 2499 lock.reset(); 2500 if (success) 2501 request->SendBitmapResult(bitmap.Pass()); 2502} 2503 2504void GLRenderer::GetFramebufferTexture(unsigned texture_id, 2505 ResourceFormat texture_format, 2506 const gfx::Rect& window_rect) { 2507 DCHECK(texture_id); 2508 DCHECK_GE(window_rect.x(), 0); 2509 DCHECK_GE(window_rect.y(), 0); 2510 DCHECK_LE(window_rect.right(), current_surface_size_.width()); 2511 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); 2512 2513 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, texture_id)); 2514 GLC(gl_, 2515 gl_->CopyTexImage2D(GL_TEXTURE_2D, 2516 0, 2517 GLDataFormat(texture_format), 2518 window_rect.x(), 2519 window_rect.y(), 2520 window_rect.width(), 2521 window_rect.height(), 2522 0)); 2523 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, 0)); 2524} 2525 2526bool GLRenderer::UseScopedTexture(DrawingFrame* frame, 2527 const ScopedResource* texture, 2528 const gfx::Rect& viewport_rect) { 2529 DCHECK(texture->id()); 2530 frame->current_render_pass = NULL; 2531 frame->current_texture = texture; 2532 2533 return BindFramebufferToTexture(frame, texture, viewport_rect); 2534} 2535 2536void GLRenderer::BindFramebufferToOutputSurface(DrawingFrame* frame) { 2537 current_framebuffer_lock_.reset(); 2538 output_surface_->BindFramebuffer(); 2539 2540 if (output_surface_->HasExternalStencilTest()) { 2541 SetStencilEnabled(true); 2542 GLC(gl_, gl_->StencilFunc(GL_EQUAL, 1, 1)); 2543 } else { 2544 SetStencilEnabled(false); 2545 } 2546} 2547 2548bool GLRenderer::BindFramebufferToTexture(DrawingFrame* frame, 2549 const ScopedResource* texture, 2550 const gfx::Rect& target_rect) { 2551 DCHECK(texture->id()); 2552 2553 current_framebuffer_lock_.reset(); 2554 2555 SetStencilEnabled(false); 2556 GLC(gl_, gl_->BindFramebuffer(GL_FRAMEBUFFER, offscreen_framebuffer_id_)); 2557 current_framebuffer_lock_ = 2558 make_scoped_ptr(new ResourceProvider::ScopedWriteLockGL( 2559 resource_provider_, texture->id())); 2560 unsigned texture_id = current_framebuffer_lock_->texture_id(); 2561 GLC(gl_, 2562 gl_->FramebufferTexture2D( 2563 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0)); 2564 2565 DCHECK(gl_->CheckFramebufferStatus(GL_FRAMEBUFFER) == 2566 GL_FRAMEBUFFER_COMPLETE || 2567 IsContextLost()); 2568 2569 InitializeViewport( 2570 frame, target_rect, gfx::Rect(target_rect.size()), target_rect.size()); 2571 return true; 2572} 2573 2574void GLRenderer::SetScissorTestRect(const gfx::Rect& scissor_rect) { 2575 EnsureScissorTestEnabled(); 2576 2577 // Don't unnecessarily ask the context to change the scissor, because it 2578 // may cause undesired GPU pipeline flushes. 2579 if (scissor_rect == scissor_rect_ && !scissor_rect_needs_reset_) 2580 return; 2581 2582 scissor_rect_ = scissor_rect; 2583 FlushTextureQuadCache(); 2584 GLC(gl_, 2585 gl_->Scissor(scissor_rect.x(), 2586 scissor_rect.y(), 2587 scissor_rect.width(), 2588 scissor_rect.height())); 2589 2590 scissor_rect_needs_reset_ = false; 2591} 2592 2593void GLRenderer::SetDrawViewport(const gfx::Rect& window_space_viewport) { 2594 viewport_ = window_space_viewport; 2595 GLC(gl_, 2596 gl_->Viewport(window_space_viewport.x(), 2597 window_space_viewport.y(), 2598 window_space_viewport.width(), 2599 window_space_viewport.height())); 2600} 2601 2602void GLRenderer::InitializeSharedObjects() { 2603 TRACE_EVENT0("cc", "GLRenderer::InitializeSharedObjects"); 2604 2605 // Create an FBO for doing offscreen rendering. 2606 GLC(gl_, gl_->GenFramebuffers(1, &offscreen_framebuffer_id_)); 2607 2608 shared_geometry_ = make_scoped_ptr( 2609 new GeometryBinding(gl_, QuadVertexRect())); 2610} 2611 2612const GLRenderer::TileCheckerboardProgram* 2613GLRenderer::GetTileCheckerboardProgram() { 2614 if (!tile_checkerboard_program_.initialized()) { 2615 TRACE_EVENT0("cc", "GLRenderer::checkerboardProgram::initalize"); 2616 tile_checkerboard_program_.Initialize(output_surface_->context_provider(), 2617 TexCoordPrecisionNA, 2618 SamplerTypeNA); 2619 } 2620 return &tile_checkerboard_program_; 2621} 2622 2623const GLRenderer::DebugBorderProgram* GLRenderer::GetDebugBorderProgram() { 2624 if (!debug_border_program_.initialized()) { 2625 TRACE_EVENT0("cc", "GLRenderer::debugBorderProgram::initialize"); 2626 debug_border_program_.Initialize(output_surface_->context_provider(), 2627 TexCoordPrecisionNA, 2628 SamplerTypeNA); 2629 } 2630 return &debug_border_program_; 2631} 2632 2633const GLRenderer::SolidColorProgram* GLRenderer::GetSolidColorProgram() { 2634 if (!solid_color_program_.initialized()) { 2635 TRACE_EVENT0("cc", "GLRenderer::solidColorProgram::initialize"); 2636 solid_color_program_.Initialize(output_surface_->context_provider(), 2637 TexCoordPrecisionNA, 2638 SamplerTypeNA); 2639 } 2640 return &solid_color_program_; 2641} 2642 2643const GLRenderer::SolidColorProgramAA* GLRenderer::GetSolidColorProgramAA() { 2644 if (!solid_color_program_aa_.initialized()) { 2645 TRACE_EVENT0("cc", "GLRenderer::solidColorProgramAA::initialize"); 2646 solid_color_program_aa_.Initialize(output_surface_->context_provider(), 2647 TexCoordPrecisionNA, 2648 SamplerTypeNA); 2649 } 2650 return &solid_color_program_aa_; 2651} 2652 2653const GLRenderer::RenderPassProgram* GLRenderer::GetRenderPassProgram( 2654 TexCoordPrecision precision) { 2655 DCHECK_GE(precision, 0); 2656 DCHECK_LT(precision, NumTexCoordPrecisions); 2657 RenderPassProgram* program = &render_pass_program_[precision]; 2658 if (!program->initialized()) { 2659 TRACE_EVENT0("cc", "GLRenderer::renderPassProgram::initialize"); 2660 program->Initialize( 2661 output_surface_->context_provider(), precision, SamplerType2D); 2662 } 2663 return program; 2664} 2665 2666const GLRenderer::RenderPassProgramAA* GLRenderer::GetRenderPassProgramAA( 2667 TexCoordPrecision precision) { 2668 DCHECK_GE(precision, 0); 2669 DCHECK_LT(precision, NumTexCoordPrecisions); 2670 RenderPassProgramAA* program = &render_pass_program_aa_[precision]; 2671 if (!program->initialized()) { 2672 TRACE_EVENT0("cc", "GLRenderer::renderPassProgramAA::initialize"); 2673 program->Initialize( 2674 output_surface_->context_provider(), precision, SamplerType2D); 2675 } 2676 return program; 2677} 2678 2679const GLRenderer::RenderPassMaskProgram* GLRenderer::GetRenderPassMaskProgram( 2680 TexCoordPrecision precision) { 2681 DCHECK_GE(precision, 0); 2682 DCHECK_LT(precision, NumTexCoordPrecisions); 2683 RenderPassMaskProgram* program = &render_pass_mask_program_[precision]; 2684 if (!program->initialized()) { 2685 TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgram::initialize"); 2686 program->Initialize( 2687 output_surface_->context_provider(), precision, SamplerType2D); 2688 } 2689 return program; 2690} 2691 2692const GLRenderer::RenderPassMaskProgramAA* 2693GLRenderer::GetRenderPassMaskProgramAA(TexCoordPrecision precision) { 2694 DCHECK_GE(precision, 0); 2695 DCHECK_LT(precision, NumTexCoordPrecisions); 2696 RenderPassMaskProgramAA* program = &render_pass_mask_program_aa_[precision]; 2697 if (!program->initialized()) { 2698 TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgramAA::initialize"); 2699 program->Initialize( 2700 output_surface_->context_provider(), precision, SamplerType2D); 2701 } 2702 return program; 2703} 2704 2705const GLRenderer::RenderPassColorMatrixProgram* 2706GLRenderer::GetRenderPassColorMatrixProgram(TexCoordPrecision precision) { 2707 DCHECK_GE(precision, 0); 2708 DCHECK_LT(precision, NumTexCoordPrecisions); 2709 RenderPassColorMatrixProgram* program = 2710 &render_pass_color_matrix_program_[precision]; 2711 if (!program->initialized()) { 2712 TRACE_EVENT0("cc", "GLRenderer::renderPassColorMatrixProgram::initialize"); 2713 program->Initialize( 2714 output_surface_->context_provider(), precision, SamplerType2D); 2715 } 2716 return program; 2717} 2718 2719const GLRenderer::RenderPassColorMatrixProgramAA* 2720GLRenderer::GetRenderPassColorMatrixProgramAA(TexCoordPrecision precision) { 2721 DCHECK_GE(precision, 0); 2722 DCHECK_LT(precision, NumTexCoordPrecisions); 2723 RenderPassColorMatrixProgramAA* program = 2724 &render_pass_color_matrix_program_aa_[precision]; 2725 if (!program->initialized()) { 2726 TRACE_EVENT0("cc", 2727 "GLRenderer::renderPassColorMatrixProgramAA::initialize"); 2728 program->Initialize( 2729 output_surface_->context_provider(), precision, SamplerType2D); 2730 } 2731 return program; 2732} 2733 2734const GLRenderer::RenderPassMaskColorMatrixProgram* 2735GLRenderer::GetRenderPassMaskColorMatrixProgram(TexCoordPrecision precision) { 2736 DCHECK_GE(precision, 0); 2737 DCHECK_LT(precision, NumTexCoordPrecisions); 2738 RenderPassMaskColorMatrixProgram* program = 2739 &render_pass_mask_color_matrix_program_[precision]; 2740 if (!program->initialized()) { 2741 TRACE_EVENT0("cc", 2742 "GLRenderer::renderPassMaskColorMatrixProgram::initialize"); 2743 program->Initialize( 2744 output_surface_->context_provider(), precision, SamplerType2D); 2745 } 2746 return program; 2747} 2748 2749const GLRenderer::RenderPassMaskColorMatrixProgramAA* 2750GLRenderer::GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision) { 2751 DCHECK_GE(precision, 0); 2752 DCHECK_LT(precision, NumTexCoordPrecisions); 2753 RenderPassMaskColorMatrixProgramAA* program = 2754 &render_pass_mask_color_matrix_program_aa_[precision]; 2755 if (!program->initialized()) { 2756 TRACE_EVENT0("cc", 2757 "GLRenderer::renderPassMaskColorMatrixProgramAA::initialize"); 2758 program->Initialize( 2759 output_surface_->context_provider(), precision, SamplerType2D); 2760 } 2761 return program; 2762} 2763 2764const GLRenderer::TileProgram* GLRenderer::GetTileProgram( 2765 TexCoordPrecision precision, 2766 SamplerType sampler) { 2767 DCHECK_GE(precision, 0); 2768 DCHECK_LT(precision, NumTexCoordPrecisions); 2769 DCHECK_GE(sampler, 0); 2770 DCHECK_LT(sampler, NumSamplerTypes); 2771 TileProgram* program = &tile_program_[precision][sampler]; 2772 if (!program->initialized()) { 2773 TRACE_EVENT0("cc", "GLRenderer::tileProgram::initialize"); 2774 program->Initialize( 2775 output_surface_->context_provider(), precision, sampler); 2776 } 2777 return program; 2778} 2779 2780const GLRenderer::TileProgramOpaque* GLRenderer::GetTileProgramOpaque( 2781 TexCoordPrecision precision, 2782 SamplerType sampler) { 2783 DCHECK_GE(precision, 0); 2784 DCHECK_LT(precision, NumTexCoordPrecisions); 2785 DCHECK_GE(sampler, 0); 2786 DCHECK_LT(sampler, NumSamplerTypes); 2787 TileProgramOpaque* program = &tile_program_opaque_[precision][sampler]; 2788 if (!program->initialized()) { 2789 TRACE_EVENT0("cc", "GLRenderer::tileProgramOpaque::initialize"); 2790 program->Initialize( 2791 output_surface_->context_provider(), precision, sampler); 2792 } 2793 return program; 2794} 2795 2796const GLRenderer::TileProgramAA* GLRenderer::GetTileProgramAA( 2797 TexCoordPrecision precision, 2798 SamplerType sampler) { 2799 DCHECK_GE(precision, 0); 2800 DCHECK_LT(precision, NumTexCoordPrecisions); 2801 DCHECK_GE(sampler, 0); 2802 DCHECK_LT(sampler, NumSamplerTypes); 2803 TileProgramAA* program = &tile_program_aa_[precision][sampler]; 2804 if (!program->initialized()) { 2805 TRACE_EVENT0("cc", "GLRenderer::tileProgramAA::initialize"); 2806 program->Initialize( 2807 output_surface_->context_provider(), precision, sampler); 2808 } 2809 return program; 2810} 2811 2812const GLRenderer::TileProgramSwizzle* GLRenderer::GetTileProgramSwizzle( 2813 TexCoordPrecision precision, 2814 SamplerType sampler) { 2815 DCHECK_GE(precision, 0); 2816 DCHECK_LT(precision, NumTexCoordPrecisions); 2817 DCHECK_GE(sampler, 0); 2818 DCHECK_LT(sampler, NumSamplerTypes); 2819 TileProgramSwizzle* program = &tile_program_swizzle_[precision][sampler]; 2820 if (!program->initialized()) { 2821 TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzle::initialize"); 2822 program->Initialize( 2823 output_surface_->context_provider(), precision, sampler); 2824 } 2825 return program; 2826} 2827 2828const GLRenderer::TileProgramSwizzleOpaque* 2829GLRenderer::GetTileProgramSwizzleOpaque(TexCoordPrecision precision, 2830 SamplerType sampler) { 2831 DCHECK_GE(precision, 0); 2832 DCHECK_LT(precision, NumTexCoordPrecisions); 2833 DCHECK_GE(sampler, 0); 2834 DCHECK_LT(sampler, NumSamplerTypes); 2835 TileProgramSwizzleOpaque* program = 2836 &tile_program_swizzle_opaque_[precision][sampler]; 2837 if (!program->initialized()) { 2838 TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleOpaque::initialize"); 2839 program->Initialize( 2840 output_surface_->context_provider(), precision, sampler); 2841 } 2842 return program; 2843} 2844 2845const GLRenderer::TileProgramSwizzleAA* GLRenderer::GetTileProgramSwizzleAA( 2846 TexCoordPrecision precision, 2847 SamplerType sampler) { 2848 DCHECK_GE(precision, 0); 2849 DCHECK_LT(precision, NumTexCoordPrecisions); 2850 DCHECK_GE(sampler, 0); 2851 DCHECK_LT(sampler, NumSamplerTypes); 2852 TileProgramSwizzleAA* program = &tile_program_swizzle_aa_[precision][sampler]; 2853 if (!program->initialized()) { 2854 TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleAA::initialize"); 2855 program->Initialize( 2856 output_surface_->context_provider(), precision, sampler); 2857 } 2858 return program; 2859} 2860 2861const GLRenderer::TextureProgram* GLRenderer::GetTextureProgram( 2862 TexCoordPrecision precision) { 2863 DCHECK_GE(precision, 0); 2864 DCHECK_LT(precision, NumTexCoordPrecisions); 2865 TextureProgram* program = &texture_program_[precision]; 2866 if (!program->initialized()) { 2867 TRACE_EVENT0("cc", "GLRenderer::textureProgram::initialize"); 2868 program->Initialize( 2869 output_surface_->context_provider(), precision, SamplerType2D); 2870 } 2871 return program; 2872} 2873 2874const GLRenderer::NonPremultipliedTextureProgram* 2875GLRenderer::GetNonPremultipliedTextureProgram(TexCoordPrecision precision) { 2876 DCHECK_GE(precision, 0); 2877 DCHECK_LT(precision, NumTexCoordPrecisions); 2878 NonPremultipliedTextureProgram* program = 2879 &nonpremultiplied_texture_program_[precision]; 2880 if (!program->initialized()) { 2881 TRACE_EVENT0("cc", 2882 "GLRenderer::NonPremultipliedTextureProgram::Initialize"); 2883 program->Initialize( 2884 output_surface_->context_provider(), precision, SamplerType2D); 2885 } 2886 return program; 2887} 2888 2889const GLRenderer::TextureBackgroundProgram* 2890GLRenderer::GetTextureBackgroundProgram(TexCoordPrecision precision) { 2891 DCHECK_GE(precision, 0); 2892 DCHECK_LT(precision, NumTexCoordPrecisions); 2893 TextureBackgroundProgram* program = &texture_background_program_[precision]; 2894 if (!program->initialized()) { 2895 TRACE_EVENT0("cc", "GLRenderer::textureProgram::initialize"); 2896 program->Initialize( 2897 output_surface_->context_provider(), precision, SamplerType2D); 2898 } 2899 return program; 2900} 2901 2902const GLRenderer::NonPremultipliedTextureBackgroundProgram* 2903GLRenderer::GetNonPremultipliedTextureBackgroundProgram( 2904 TexCoordPrecision precision) { 2905 DCHECK_GE(precision, 0); 2906 DCHECK_LT(precision, NumTexCoordPrecisions); 2907 NonPremultipliedTextureBackgroundProgram* program = 2908 &nonpremultiplied_texture_background_program_[precision]; 2909 if (!program->initialized()) { 2910 TRACE_EVENT0("cc", 2911 "GLRenderer::NonPremultipliedTextureProgram::Initialize"); 2912 program->Initialize( 2913 output_surface_->context_provider(), precision, SamplerType2D); 2914 } 2915 return program; 2916} 2917 2918const GLRenderer::TextureProgram* GLRenderer::GetTextureIOSurfaceProgram( 2919 TexCoordPrecision precision) { 2920 DCHECK_GE(precision, 0); 2921 DCHECK_LT(precision, NumTexCoordPrecisions); 2922 TextureProgram* program = &texture_io_surface_program_[precision]; 2923 if (!program->initialized()) { 2924 TRACE_EVENT0("cc", "GLRenderer::textureIOSurfaceProgram::initialize"); 2925 program->Initialize( 2926 output_surface_->context_provider(), precision, SamplerType2DRect); 2927 } 2928 return program; 2929} 2930 2931const GLRenderer::VideoYUVProgram* GLRenderer::GetVideoYUVProgram( 2932 TexCoordPrecision precision) { 2933 DCHECK_GE(precision, 0); 2934 DCHECK_LT(precision, NumTexCoordPrecisions); 2935 VideoYUVProgram* program = &video_yuv_program_[precision]; 2936 if (!program->initialized()) { 2937 TRACE_EVENT0("cc", "GLRenderer::videoYUVProgram::initialize"); 2938 program->Initialize( 2939 output_surface_->context_provider(), precision, SamplerType2D); 2940 } 2941 return program; 2942} 2943 2944const GLRenderer::VideoYUVAProgram* GLRenderer::GetVideoYUVAProgram( 2945 TexCoordPrecision precision) { 2946 DCHECK_GE(precision, 0); 2947 DCHECK_LT(precision, NumTexCoordPrecisions); 2948 VideoYUVAProgram* program = &video_yuva_program_[precision]; 2949 if (!program->initialized()) { 2950 TRACE_EVENT0("cc", "GLRenderer::videoYUVAProgram::initialize"); 2951 program->Initialize( 2952 output_surface_->context_provider(), precision, SamplerType2D); 2953 } 2954 return program; 2955} 2956 2957const GLRenderer::VideoStreamTextureProgram* 2958GLRenderer::GetVideoStreamTextureProgram(TexCoordPrecision precision) { 2959 if (!Capabilities().using_egl_image) 2960 return NULL; 2961 DCHECK_GE(precision, 0); 2962 DCHECK_LT(precision, NumTexCoordPrecisions); 2963 VideoStreamTextureProgram* program = 2964 &video_stream_texture_program_[precision]; 2965 if (!program->initialized()) { 2966 TRACE_EVENT0("cc", "GLRenderer::streamTextureProgram::initialize"); 2967 program->Initialize( 2968 output_surface_->context_provider(), precision, SamplerTypeExternalOES); 2969 } 2970 return program; 2971} 2972 2973void GLRenderer::CleanupSharedObjects() { 2974 shared_geometry_.reset(); 2975 2976 for (int i = 0; i < NumTexCoordPrecisions; ++i) { 2977 for (int j = 0; j < NumSamplerTypes; ++j) { 2978 tile_program_[i][j].Cleanup(gl_); 2979 tile_program_opaque_[i][j].Cleanup(gl_); 2980 tile_program_swizzle_[i][j].Cleanup(gl_); 2981 tile_program_swizzle_opaque_[i][j].Cleanup(gl_); 2982 tile_program_aa_[i][j].Cleanup(gl_); 2983 tile_program_swizzle_aa_[i][j].Cleanup(gl_); 2984 } 2985 2986 render_pass_mask_program_[i].Cleanup(gl_); 2987 render_pass_program_[i].Cleanup(gl_); 2988 render_pass_mask_program_aa_[i].Cleanup(gl_); 2989 render_pass_program_aa_[i].Cleanup(gl_); 2990 render_pass_color_matrix_program_[i].Cleanup(gl_); 2991 render_pass_mask_color_matrix_program_aa_[i].Cleanup(gl_); 2992 render_pass_color_matrix_program_aa_[i].Cleanup(gl_); 2993 render_pass_mask_color_matrix_program_[i].Cleanup(gl_); 2994 2995 texture_program_[i].Cleanup(gl_); 2996 nonpremultiplied_texture_program_[i].Cleanup(gl_); 2997 texture_background_program_[i].Cleanup(gl_); 2998 nonpremultiplied_texture_background_program_[i].Cleanup(gl_); 2999 texture_io_surface_program_[i].Cleanup(gl_); 3000 3001 video_yuv_program_[i].Cleanup(gl_); 3002 video_yuva_program_[i].Cleanup(gl_); 3003 video_stream_texture_program_[i].Cleanup(gl_); 3004 } 3005 3006 tile_checkerboard_program_.Cleanup(gl_); 3007 3008 debug_border_program_.Cleanup(gl_); 3009 solid_color_program_.Cleanup(gl_); 3010 solid_color_program_aa_.Cleanup(gl_); 3011 3012 if (offscreen_framebuffer_id_) 3013 GLC(gl_, gl_->DeleteFramebuffers(1, &offscreen_framebuffer_id_)); 3014 3015 if (on_demand_tile_raster_resource_id_) 3016 resource_provider_->DeleteResource(on_demand_tile_raster_resource_id_); 3017 3018 ReleaseRenderPassTextures(); 3019} 3020 3021void GLRenderer::ReinitializeGLState() { 3022 // Bind the common vertex attributes used for drawing all the layers. 3023 shared_geometry_->PrepareForDraw(); 3024 3025 GLC(gl_, gl_->Disable(GL_DEPTH_TEST)); 3026 GLC(gl_, gl_->Disable(GL_CULL_FACE)); 3027 GLC(gl_, gl_->ColorMask(true, true, true, true)); 3028 GLC(gl_, gl_->Disable(GL_STENCIL_TEST)); 3029 stencil_shadow_ = false; 3030 GLC(gl_, gl_->Enable(GL_BLEND)); 3031 blend_shadow_ = true; 3032 GLC(gl_, gl_->BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); 3033 GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0)); 3034 program_shadow_ = 0; 3035 3036 // Make sure scissoring starts as disabled. 3037 is_scissor_enabled_ = false; 3038 GLC(gl_, gl_->Disable(GL_SCISSOR_TEST)); 3039 scissor_rect_needs_reset_ = true; 3040} 3041 3042bool GLRenderer::IsContextLost() { 3043 return output_surface_->context_provider()->IsContextLost(); 3044} 3045 3046} // namespace cc 3047