| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013 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/output_surface.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/message_loop/message_loop.h" | |
| 9 #include "base/trace_event/trace_event.h" | |
| 10 #include "cc/output/output_surface_client.h" | |
| 11 #include "gpu/GLES2/gl2extchromium.h" | |
| 12 #include "gpu/command_buffer/client/gles2_interface.h" | |
| 13 #include "ui/gfx/geometry/rect.h" | |
| 14 #include "ui/gfx/geometry/size.h" | |
| 15 | |
| 16 | |
| 17 namespace cc { | |
| 18 | |
| 19 OutputSurface::OutputSurface( | |
| 20 const scoped_refptr<ContextProvider>& context_provider, | |
| 21 const scoped_refptr<ContextProvider>& worker_context_provider, | |
| 22 scoped_ptr<SoftwareOutputDevice> software_device) | |
| 23 : client_(NULL), | |
| 24 context_provider_(context_provider), | |
| 25 worker_context_provider_(worker_context_provider), | |
| 26 software_device_(software_device.Pass()), | |
| 27 device_scale_factor_(-1), | |
| 28 external_stencil_test_enabled_(false), | |
| 29 weak_ptr_factory_(this) { | |
| 30 } | |
| 31 | |
| 32 OutputSurface::OutputSurface( | |
| 33 const scoped_refptr<ContextProvider>& context_provider) | |
| 34 : OutputSurface(context_provider, nullptr, nullptr) { | |
| 35 } | |
| 36 | |
| 37 OutputSurface::OutputSurface( | |
| 38 const scoped_refptr<ContextProvider>& context_provider, | |
| 39 const scoped_refptr<ContextProvider>& worker_context_provider) | |
| 40 : OutputSurface(context_provider, worker_context_provider, nullptr) { | |
| 41 } | |
| 42 | |
| 43 OutputSurface::OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device) | |
| 44 : OutputSurface(nullptr, nullptr, software_device.Pass()) { | |
| 45 } | |
| 46 | |
| 47 OutputSurface::OutputSurface( | |
| 48 const scoped_refptr<ContextProvider>& context_provider, | |
| 49 scoped_ptr<SoftwareOutputDevice> software_device) | |
| 50 : OutputSurface(context_provider, nullptr, software_device.Pass()) { | |
| 51 } | |
| 52 | |
| 53 void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase, | |
| 54 base::TimeDelta interval) { | |
| 55 TRACE_EVENT2("cc", | |
| 56 "OutputSurface::CommitVSyncParameters", | |
| 57 "timebase", | |
| 58 (timebase - base::TimeTicks()).InSecondsF(), | |
| 59 "interval", | |
| 60 interval.InSecondsF()); | |
| 61 client_->CommitVSyncParameters(timebase, interval); | |
| 62 } | |
| 63 | |
| 64 // Forwarded to OutputSurfaceClient | |
| 65 void OutputSurface::SetNeedsRedrawRect(const gfx::Rect& damage_rect) { | |
| 66 TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect"); | |
| 67 client_->SetNeedsRedrawRect(damage_rect); | |
| 68 } | |
| 69 | |
| 70 void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) { | |
| 71 client_->ReclaimResources(ack); | |
| 72 } | |
| 73 | |
| 74 void OutputSurface::DidLoseOutputSurface() { | |
| 75 TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface"); | |
| 76 client_->DidLoseOutputSurface(); | |
| 77 } | |
| 78 | |
| 79 void OutputSurface::SetExternalStencilTest(bool enabled) { | |
| 80 external_stencil_test_enabled_ = enabled; | |
| 81 } | |
| 82 | |
| 83 void OutputSurface::SetExternalDrawConstraints( | |
| 84 const gfx::Transform& transform, | |
| 85 const gfx::Rect& viewport, | |
| 86 const gfx::Rect& clip, | |
| 87 const gfx::Rect& viewport_rect_for_tile_priority, | |
| 88 const gfx::Transform& transform_for_tile_priority, | |
| 89 bool resourceless_software_draw) { | |
| 90 client_->SetExternalDrawConstraints(transform, | |
| 91 viewport, | |
| 92 clip, | |
| 93 viewport_rect_for_tile_priority, | |
| 94 transform_for_tile_priority, | |
| 95 resourceless_software_draw); | |
| 96 } | |
| 97 | |
| 98 OutputSurface::~OutputSurface() { | |
| 99 ResetContext3d(); | |
| 100 } | |
| 101 | |
| 102 bool OutputSurface::HasExternalStencilTest() const { | |
| 103 return external_stencil_test_enabled_; | |
| 104 } | |
| 105 | |
| 106 bool OutputSurface::BindToClient(OutputSurfaceClient* client) { | |
| 107 DCHECK(client); | |
| 108 client_ = client; | |
| 109 bool success = true; | |
| 110 | |
| 111 if (context_provider_.get()) { | |
| 112 success = context_provider_->BindToCurrentThread(); | |
| 113 if (success) | |
| 114 SetUpContext3d(); | |
| 115 } | |
| 116 | |
| 117 if (success && worker_context_provider_.get()) { | |
| 118 success = worker_context_provider_->BindToCurrentThread(); | |
| 119 if (success) { | |
| 120 worker_context_provider_->SetupLock(); | |
| 121 // The destructor resets the context lost callback, so base::Unretained | |
| 122 // is safe, as long as the worker threads stop using the context before | |
| 123 // the output surface is destroyed. | |
| 124 worker_context_provider_->SetLostContextCallback(base::Bind( | |
| 125 &OutputSurface::DidLoseOutputSurface, base::Unretained(this))); | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 if (!success) | |
| 130 client_ = NULL; | |
| 131 | |
| 132 return success; | |
| 133 } | |
| 134 | |
| 135 bool OutputSurface::InitializeAndSetContext3d( | |
| 136 scoped_refptr<ContextProvider> context_provider, | |
| 137 scoped_refptr<ContextProvider> worker_context_provider) { | |
| 138 DCHECK(!context_provider_.get()); | |
| 139 DCHECK(context_provider.get()); | |
| 140 DCHECK(client_); | |
| 141 | |
| 142 bool success = context_provider->BindToCurrentThread(); | |
| 143 if (success) { | |
| 144 context_provider_ = context_provider; | |
| 145 SetUpContext3d(); | |
| 146 } | |
| 147 if (success && worker_context_provider.get()) { | |
| 148 success = worker_context_provider->BindToCurrentThread(); | |
| 149 if (success) { | |
| 150 worker_context_provider_ = worker_context_provider; | |
| 151 // The destructor resets the context lost callback, so base::Unretained | |
| 152 // is safe, as long as the worker threads stop using the context before | |
| 153 // the output surface is destroyed. | |
| 154 worker_context_provider_->SetLostContextCallback(base::Bind( | |
| 155 &OutputSurface::DidLoseOutputSurface, base::Unretained(this))); | |
| 156 } | |
| 157 } | |
| 158 | |
| 159 if (!success) | |
| 160 ResetContext3d(); | |
| 161 else | |
| 162 client_->DeferredInitialize(); | |
| 163 | |
| 164 return success; | |
| 165 } | |
| 166 | |
| 167 void OutputSurface::ReleaseGL() { | |
| 168 DCHECK(client_); | |
| 169 DCHECK(context_provider_.get()); | |
| 170 client_->ReleaseGL(); | |
| 171 DCHECK(!context_provider_.get()); | |
| 172 } | |
| 173 | |
| 174 void OutputSurface::SetUpContext3d() { | |
| 175 DCHECK(context_provider_.get()); | |
| 176 DCHECK(client_); | |
| 177 | |
| 178 context_provider_->SetLostContextCallback( | |
| 179 base::Bind(&OutputSurface::DidLoseOutputSurface, | |
| 180 base::Unretained(this))); | |
| 181 } | |
| 182 | |
| 183 void OutputSurface::ReleaseContextProvider() { | |
| 184 DCHECK(client_); | |
| 185 DCHECK(context_provider_.get()); | |
| 186 ResetContext3d(); | |
| 187 } | |
| 188 | |
| 189 void OutputSurface::ResetContext3d() { | |
| 190 if (context_provider_.get()) { | |
| 191 context_provider_->SetLostContextCallback( | |
| 192 ContextProvider::LostContextCallback()); | |
| 193 } | |
| 194 if (worker_context_provider_.get()) { | |
| 195 worker_context_provider_->SetLostContextCallback( | |
| 196 ContextProvider::LostContextCallback()); | |
| 197 } | |
| 198 context_provider_ = NULL; | |
| 199 worker_context_provider_ = NULL; | |
| 200 } | |
| 201 | |
| 202 void OutputSurface::EnsureBackbuffer() { | |
| 203 if (software_device_) | |
| 204 software_device_->EnsureBackbuffer(); | |
| 205 } | |
| 206 | |
| 207 void OutputSurface::DiscardBackbuffer() { | |
| 208 if (context_provider_.get()) | |
| 209 context_provider_->ContextGL()->DiscardBackbufferCHROMIUM(); | |
| 210 if (software_device_) | |
| 211 software_device_->DiscardBackbuffer(); | |
| 212 } | |
| 213 | |
| 214 void OutputSurface::Reshape(const gfx::Size& size, float scale_factor) { | |
| 215 if (size == surface_size_ && scale_factor == device_scale_factor_) | |
| 216 return; | |
| 217 | |
| 218 surface_size_ = size; | |
| 219 device_scale_factor_ = scale_factor; | |
| 220 if (context_provider_.get()) { | |
| 221 context_provider_->ContextGL()->ResizeCHROMIUM( | |
| 222 size.width(), size.height(), scale_factor); | |
| 223 } | |
| 224 if (software_device_) | |
| 225 software_device_->Resize(size, scale_factor); | |
| 226 } | |
| 227 | |
| 228 gfx::Size OutputSurface::SurfaceSize() const { | |
| 229 return surface_size_; | |
| 230 } | |
| 231 | |
| 232 void OutputSurface::BindFramebuffer() { | |
| 233 DCHECK(context_provider_.get()); | |
| 234 context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, 0); | |
| 235 } | |
| 236 | |
| 237 void OutputSurface::PostSwapBuffersComplete() { | |
| 238 base::MessageLoop::current()->PostTask( | |
| 239 FROM_HERE, | |
| 240 base::Bind(&OutputSurface::OnSwapBuffersComplete, | |
| 241 weak_ptr_factory_.GetWeakPtr())); | |
| 242 } | |
| 243 | |
| 244 // We don't post tasks bound to the client directly since they might run | |
| 245 // after the OutputSurface has been destroyed. | |
| 246 void OutputSurface::OnSwapBuffersComplete() { | |
| 247 client_->DidSwapBuffersComplete(); | |
| 248 } | |
| 249 | |
| 250 } // namespace cc | |
| OLD | NEW |