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