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 "gpu/command_buffer/client/gles2_interface.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 io_surface_resource_id_(0) {} 26 27 IOSurfaceLayerImpl::~IOSurfaceLayerImpl() { 28 if (!io_surface_texture_id_) 29 return; 30 31 DestroyTexture(); 32 } 33 34 void IOSurfaceLayerImpl::DestroyTexture() { 35 if (io_surface_resource_id_) { 36 ResourceProvider* resource_provider = 37 layer_tree_impl()->resource_provider(); 38 resource_provider->DeleteResource(io_surface_resource_id_); 39 io_surface_resource_id_ = 0; 40 } 41 42 if (io_surface_texture_id_) { 43 ContextProvider* context_provider = 44 layer_tree_impl()->output_surface()->context_provider().get(); 45 // TODO(skaslev): Implement this path for software compositing. 46 if (context_provider) 47 context_provider->ContextGL()->DeleteTextures(1, &io_surface_texture_id_); 48 io_surface_texture_id_ = 0; 49 } 50 } 51 52 scoped_ptr<LayerImpl> IOSurfaceLayerImpl::CreateLayerImpl( 53 LayerTreeImpl* tree_impl) { 54 return IOSurfaceLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>(); 55 } 56 57 void IOSurfaceLayerImpl::PushPropertiesTo(LayerImpl* layer) { 58 LayerImpl::PushPropertiesTo(layer); 59 60 IOSurfaceLayerImpl* io_surface_layer = 61 static_cast<IOSurfaceLayerImpl*>(layer); 62 io_surface_layer->SetIOSurfaceProperties(io_surface_id_, io_surface_size_); 63 } 64 65 bool IOSurfaceLayerImpl::WillDraw(DrawMode draw_mode, 66 ResourceProvider* resource_provider) { 67 if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE) 68 return false; 69 70 if (io_surface_changed_) { 71 ContextProvider* context_provider = 72 layer_tree_impl()->output_surface()->context_provider().get(); 73 if (!context_provider) { 74 // TODO(skaslev): Implement this path for software compositing. 75 return false; 76 } 77 78 gpu::gles2::GLES2Interface* gl = context_provider->ContextGL(); 79 80 // TODO(ernstm): Do this in a way that we can track memory usage. 81 if (!io_surface_texture_id_) { 82 gl->GenTextures(1, &io_surface_texture_id_); 83 io_surface_resource_id_ = 84 resource_provider->CreateResourceFromExternalTexture( 85 GL_TEXTURE_RECTANGLE_ARB, 86 io_surface_texture_id_); 87 } 88 89 GLC(gl, gl->BindTexture(GL_TEXTURE_RECTANGLE_ARB, io_surface_texture_id_)); 90 gl->TexImageIOSurface2DCHROMIUM(GL_TEXTURE_RECTANGLE_ARB, 91 io_surface_size_.width(), 92 io_surface_size_.height(), 93 io_surface_id_, 94 0); 95 // Do not check for error conditions. texImageIOSurface2DCHROMIUM() is 96 // supposed to hold on to the last good IOSurface if the new one is already 97 // closed. This is only a possibility during live resizing of plugins. 98 // However, it seems that this is not sufficient to completely guard against 99 // garbage being drawn. If this is found to be a significant issue, it may 100 // be necessary to explicitly tell the embedder when to free the surfaces it 101 // has allocated. 102 io_surface_changed_ = false; 103 } 104 105 return LayerImpl::WillDraw(draw_mode, resource_provider); 106 } 107 108 void IOSurfaceLayerImpl::AppendQuads(QuadSink* quad_sink, 109 AppendQuadsData* append_quads_data) { 110 SharedQuadState* shared_quad_state = 111 quad_sink->UseSharedQuadState(CreateSharedQuadState()); 112 AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data); 113 114 gfx::Rect quad_rect(content_bounds()); 115 gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect()); 116 scoped_ptr<IOSurfaceDrawQuad> quad = IOSurfaceDrawQuad::Create(); 117 quad->SetNew(shared_quad_state, 118 quad_rect, 119 opaque_rect, 120 io_surface_size_, 121 io_surface_resource_id_, 122 IOSurfaceDrawQuad::FLIPPED); 123 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); 124 } 125 126 void IOSurfaceLayerImpl::DidLoseOutputSurface() { 127 // We don't have a valid texture ID in the new context; however, 128 // the IOSurface is still valid. 129 DestroyTexture(); 130 io_surface_changed_ = true; 131 } 132 133 void IOSurfaceLayerImpl::SetIOSurfaceProperties(unsigned io_surface_id, 134 gfx::Size size) { 135 if (io_surface_id_ != io_surface_id) 136 io_surface_changed_ = true; 137 138 io_surface_id_ = io_surface_id; 139 io_surface_size_ = size; 140 } 141 142 const char* IOSurfaceLayerImpl::LayerTypeAsString() const { 143 return "cc::IOSurfaceLayerImpl"; 144 } 145 146 } // namespace cc 147