1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "cc/layers/io_surface_layer_impl.h" 6 7 #include "base/strings/stringprintf.h" 8 #include "cc/layers/quad_sink.h" 9 #include "cc/output/gl_renderer.h" // For the GLC() macro. 10 #include "cc/output/output_surface.h" 11 #include "cc/quads/io_surface_draw_quad.h" 12 #include "cc/trees/layer_tree_impl.h" 13 #include "gpu/GLES2/gl2extchromium.h" 14 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" 15 #include "third_party/khronos/GLES2/gl2.h" 16 #include "third_party/khronos/GLES2/gl2ext.h" 17 18 namespace cc { 19 20 IOSurfaceLayerImpl::IOSurfaceLayerImpl(LayerTreeImpl* tree_impl, int id) 21 : LayerImpl(tree_impl, id), 22 io_surface_id_(0), 23 io_surface_changed_(false), 24 io_surface_texture_id_(0) {} 25 26 IOSurfaceLayerImpl::~IOSurfaceLayerImpl() { 27 if (!io_surface_texture_id_) 28 return; 29 30 DestroyTexture(); 31 } 32 33 void IOSurfaceLayerImpl::DestroyTexture() { 34 if (io_surface_resource_id_) { 35 ResourceProvider* resource_provider = 36 layer_tree_impl()->resource_provider(); 37 resource_provider->DeleteResource(io_surface_resource_id_); 38 io_surface_resource_id_ = 0; 39 } 40 41 if (io_surface_texture_id_) { 42 OutputSurface* output_surface = layer_tree_impl()->output_surface(); 43 // TODO(skaslev): Implement this path for software compositing. 44 WebKit::WebGraphicsContext3D* context3d = output_surface->context3d(); 45 if (context3d) 46 context3d->deleteTexture(io_surface_texture_id_); 47 io_surface_texture_id_ = 0; 48 } 49 } 50 51 scoped_ptr<LayerImpl> IOSurfaceLayerImpl::CreateLayerImpl( 52 LayerTreeImpl* tree_impl) { 53 return IOSurfaceLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>(); 54 } 55 56 void IOSurfaceLayerImpl::PushPropertiesTo(LayerImpl* layer) { 57 LayerImpl::PushPropertiesTo(layer); 58 59 IOSurfaceLayerImpl* io_surface_layer = 60 static_cast<IOSurfaceLayerImpl*>(layer); 61 io_surface_layer->SetIOSurfaceProperties(io_surface_id_, io_surface_size_); 62 } 63 64 bool IOSurfaceLayerImpl::WillDraw(DrawMode draw_mode, 65 ResourceProvider* resource_provider) { 66 if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE) 67 return false; 68 69 if (io_surface_changed_) { 70 WebKit::WebGraphicsContext3D* context3d = 71 resource_provider->GraphicsContext3D(); 72 if (!context3d) { 73 // TODO(skaslev): Implement this path for software compositing. 74 return false; 75 } 76 77 // TODO(ernstm): Do this in a way that we can track memory usage. 78 if (!io_surface_texture_id_) { 79 io_surface_texture_id_ = context3d->createTexture(); 80 io_surface_resource_id_ = 81 resource_provider->CreateResourceFromExternalTexture( 82 GL_TEXTURE_RECTANGLE_ARB, 83 io_surface_texture_id_); 84 } 85 86 GLC(context3d, 87 context3d->bindTexture(GL_TEXTURE_RECTANGLE_ARB, 88 io_surface_texture_id_)); 89 context3d->texImageIOSurface2DCHROMIUM(GL_TEXTURE_RECTANGLE_ARB, 90 io_surface_size_.width(), 91 io_surface_size_.height(), 92 io_surface_id_, 93 0); 94 // Do not check for error conditions. texImageIOSurface2DCHROMIUM() is 95 // supposed to hold on to the last good IOSurface if the new one is already 96 // closed. This is only a possibility during live resizing of plugins. 97 // However, it seems that this is not sufficient to completely guard against 98 // garbage being drawn. If this is found to be a significant issue, it may 99 // be necessary to explicitly tell the embedder when to free the surfaces it 100 // has allocated. 101 io_surface_changed_ = false; 102 } 103 104 return LayerImpl::WillDraw(draw_mode, resource_provider); 105 } 106 107 void IOSurfaceLayerImpl::AppendQuads(QuadSink* quad_sink, 108 AppendQuadsData* append_quads_data) { 109 SharedQuadState* shared_quad_state = 110 quad_sink->UseSharedQuadState(CreateSharedQuadState()); 111 AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data); 112 113 gfx::Rect quad_rect(content_bounds()); 114 gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect()); 115 scoped_ptr<IOSurfaceDrawQuad> quad = IOSurfaceDrawQuad::Create(); 116 quad->SetNew(shared_quad_state, 117 quad_rect, 118 opaque_rect, 119 io_surface_size_, 120 io_surface_resource_id_, 121 IOSurfaceDrawQuad::FLIPPED); 122 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); 123 } 124 125 void IOSurfaceLayerImpl::DidLoseOutputSurface() { 126 // We don't have a valid texture ID in the new context; however, 127 // the IOSurface is still valid. 128 DestroyTexture(); 129 io_surface_changed_ = true; 130 } 131 132 void IOSurfaceLayerImpl::SetIOSurfaceProperties(unsigned io_surface_id, 133 gfx::Size size) { 134 if (io_surface_id_ != io_surface_id) 135 io_surface_changed_ = true; 136 137 io_surface_id_ = io_surface_id; 138 io_surface_size_ = size; 139 } 140 141 const char* IOSurfaceLayerImpl::LayerTypeAsString() const { 142 return "cc::IOSurfaceLayerImpl"; 143 } 144 145 } // namespace cc 146