Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(802)

Side by Side Diff: content/common/gpu/image_transport_surface_fbo_mac.cc

Issue 454243002: Make GPU back-pressure work with remote CALayers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix flashes Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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 "content/common/gpu/image_transport_surface_fbo_mac.h"
6
7 #include "content/common/gpu/gpu_messages.h"
8 #include "content/common/gpu/image_transport_surface_iosurface_mac.h"
9 #include "ui/gfx/native_widget_types.h"
10 #include "ui/gl/gl_context.h"
11 #include "ui/gl/gl_implementation.h"
12 #include "ui/gl/gl_surface_osmesa.h"
13
14 namespace content {
15
16 ImageTransportSurfaceFBO::ImageTransportSurfaceFBO(
17 StorageProvider* storage_provider,
18 GpuChannelManager* manager,
19 GpuCommandBufferStub* stub,
20 gfx::PluginWindowHandle handle)
21 : storage_provider_(storage_provider),
22 backbuffer_suggested_allocation_(true),
23 frontbuffer_suggested_allocation_(true),
24 fbo_id_(0),
25 texture_id_(0),
26 depth_stencil_renderbuffer_id_(0),
27 has_complete_framebuffer_(false),
28 context_(NULL),
29 scale_factor_(1.f),
30 made_current_(false),
31 is_swap_buffers_pending_(false),
32 did_unschedule_(false) {
33 helper_.reset(new ImageTransportHelper(this, manager, stub, handle));
34 }
35
36 ImageTransportSurfaceFBO::~ImageTransportSurfaceFBO() {
37 }
38
39 bool ImageTransportSurfaceFBO::Initialize() {
40 // Only support IOSurfaces if the GL implementation is the native desktop GL.
41 // IO surfaces will not work with, for example, OSMesa software renderer
42 // GL contexts.
43 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL &&
44 gfx::GetGLImplementation() != gfx::kGLImplementationAppleGL)
45 return false;
46
47 if (!helper_->Initialize())
48 return false;
49
50 helper_->stub()->AddDestructionObserver(this);
51 return true;
52 }
53
54 void ImageTransportSurfaceFBO::Destroy() {
55 DestroyFramebuffer();
56
57 helper_->Destroy();
58 }
59
60 bool ImageTransportSurfaceFBO::DeferDraws() {
61 // The command buffer hit a draw/clear command that could clobber the
62 // IOSurface in use by an earlier SwapBuffers. If a Swap is pending, abort
63 // processing of the command by returning true and unschedule until the Swap
64 // Ack arrives.
65 if(did_unschedule_)
66 return true; // Still unscheduled, so just return true.
67 if (is_swap_buffers_pending_) {
68 did_unschedule_ = true;
69 helper_->SetScheduled(false);
70 return true;
71 }
72 return false;
73 }
74
75 bool ImageTransportSurfaceFBO::IsOffscreen() {
76 return false;
77 }
78
79 bool ImageTransportSurfaceFBO::OnMakeCurrent(gfx::GLContext* context) {
80 context_ = context;
81
82 if (made_current_)
83 return true;
84
85 OnResize(gfx::Size(1, 1), 1.f);
86
87 made_current_ = true;
88 return true;
89 }
90
91 unsigned int ImageTransportSurfaceFBO::GetBackingFrameBufferObject() {
92 return fbo_id_;
93 }
94
95 bool ImageTransportSurfaceFBO::SetBackbufferAllocation(bool allocation) {
96 if (backbuffer_suggested_allocation_ == allocation)
97 return true;
98 backbuffer_suggested_allocation_ = allocation;
99 AdjustBufferAllocation();
100 return true;
101 }
102
103 void ImageTransportSurfaceFBO::SetFrontbufferAllocation(bool allocation) {
104 if (frontbuffer_suggested_allocation_ == allocation)
105 return;
106 frontbuffer_suggested_allocation_ = allocation;
107 AdjustBufferAllocation();
108 }
109
110 void ImageTransportSurfaceFBO::AdjustBufferAllocation() {
111 // On mac, the frontbuffer and backbuffer are the same buffer. The buffer is
112 // free'd when both the browser and gpu processes have Unref'd the IOSurface.
113 if (!backbuffer_suggested_allocation_ &&
114 !frontbuffer_suggested_allocation_ &&
115 has_complete_framebuffer_) {
116 DestroyFramebuffer();
117 helper_->Suspend();
118 } else if (backbuffer_suggested_allocation_ && !has_complete_framebuffer_) {
119 CreateFramebuffer();
120 }
121 }
122
123 bool ImageTransportSurfaceFBO::SwapBuffers() {
124 DCHECK(backbuffer_suggested_allocation_);
125 if (!frontbuffer_suggested_allocation_)
126 return true;
127 glFlush();
128
129 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
130 params.surface_handle = storage_provider_->GetSurfaceHandle();
131 params.size = GetSize();
132 params.scale_factor = scale_factor_;
133 params.latency_info.swap(latency_info_);
134 helper_->SendAcceleratedSurfaceBuffersSwapped(params);
135
136 DCHECK(!is_swap_buffers_pending_);
137 is_swap_buffers_pending_ = true;
138
139 storage_provider_->WillSwapBuffers();
140 return true;
141 }
142
143 bool ImageTransportSurfaceFBO::PostSubBuffer(
144 int x, int y, int width, int height) {
145 DCHECK(backbuffer_suggested_allocation_);
146 if (!frontbuffer_suggested_allocation_)
147 return true;
148 glFlush();
149
150 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
151 params.surface_handle = storage_provider_->GetSurfaceHandle();
152 params.x = x;
153 params.y = y;
154 params.width = width;
155 params.height = height;
156 params.surface_size = GetSize();
157 params.surface_scale_factor = scale_factor_;
158 params.latency_info.swap(latency_info_);
159 helper_->SendAcceleratedSurfacePostSubBuffer(params);
160
161 DCHECK(!is_swap_buffers_pending_);
162 is_swap_buffers_pending_ = true;
163
164 storage_provider_->WillSwapBuffers();
165 return true;
166 }
167
168 bool ImageTransportSurfaceFBO::SupportsPostSubBuffer() {
169 return true;
170 }
171
172 gfx::Size ImageTransportSurfaceFBO::GetSize() {
173 return size_;
174 }
175
176 void* ImageTransportSurfaceFBO::GetHandle() {
177 return NULL;
178 }
179
180 void* ImageTransportSurfaceFBO::GetDisplay() {
181 return NULL;
182 }
183
184 void ImageTransportSurfaceFBO::OnBufferPresented(
185 const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
186 DCHECK(is_swap_buffers_pending_);
187
188 context_->share_group()->SetRendererID(params.renderer_id);
189 is_swap_buffers_pending_ = false;
190 if (did_unschedule_) {
191 did_unschedule_ = false;
192 helper_->SetScheduled(true);
193 }
194 }
195
196 void ImageTransportSurfaceFBO::OnResize(gfx::Size size,
197 float scale_factor) {
198 // This trace event is used in gpu_feature_browsertest.cc - the test will need
199 // to be updated if this event is changed or moved.
200 TRACE_EVENT2("gpu", "ImageTransportSurfaceFBO::OnResize",
201 "old_width", size_.width(), "new_width", size.width());
202 // Caching |context_| from OnMakeCurrent. It should still be current.
203 DCHECK(context_->IsCurrent(this));
204
205 size_ = size;
206 scale_factor_ = scale_factor;
207
208 CreateFramebuffer();
209 }
210
211 void ImageTransportSurfaceFBO::SetLatencyInfo(
212 const std::vector<ui::LatencyInfo>& latency_info) {
213 for (size_t i = 0; i < latency_info.size(); i++)
214 latency_info_.push_back(latency_info[i]);
215 }
216
217 void ImageTransportSurfaceFBO::WakeUpGpu() {
218 NOTIMPLEMENTED();
219 }
220
221 void ImageTransportSurfaceFBO::OnWillDestroyStub() {
222 helper_->stub()->RemoveDestructionObserver(this);
223 Destroy();
224 }
225
226 void ImageTransportSurfaceFBO::DestroyFramebuffer() {
227 // If we have resources to destroy, then make sure that we have a current
228 // context which we can use to delete the resources.
229 if (context_ || fbo_id_ || texture_id_ || depth_stencil_renderbuffer_id_) {
230 DCHECK(gfx::GLContext::GetCurrent() == context_);
231 DCHECK(context_->IsCurrent(this));
232 DCHECK(CGLGetCurrentContext());
233 }
234
235 if (fbo_id_) {
236 glDeleteFramebuffersEXT(1, &fbo_id_);
237 fbo_id_ = 0;
238 }
239
240 if (texture_id_) {
241 glDeleteTextures(1, &texture_id_);
242 texture_id_ = 0;
243 }
244
245 if (depth_stencil_renderbuffer_id_) {
246 glDeleteRenderbuffersEXT(1, &depth_stencil_renderbuffer_id_);
247 depth_stencil_renderbuffer_id_ = 0;
248 }
249
250 storage_provider_->FreeColorBufferStorage();
251
252 has_complete_framebuffer_ = false;
253 }
254
255 void ImageTransportSurfaceFBO::CreateFramebuffer() {
256 gfx::Size new_rounded_size = storage_provider_->GetRoundedSize(size_);
257
258 // Only recreate surface when the rounded up size has changed.
259 if (has_complete_framebuffer_ && new_rounded_size == rounded_size_)
260 return;
261
262 // This trace event is used in gpu_feature_browsertest.cc - the test will need
263 // to be updated if this event is changed or moved.
264 TRACE_EVENT2("gpu", "ImageTransportSurfaceFBO::CreateFramebuffer",
265 "width", new_rounded_size.width(),
266 "height", new_rounded_size.height());
267
268 rounded_size_ = new_rounded_size;
269
270 // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on
271 // Mac OS X and is required for IOSurface interoperability.
272 GLint previous_texture_id = 0;
273 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &previous_texture_id);
274
275 // Free the old IO Surface first to reduce memory fragmentation.
276 DestroyFramebuffer();
277
278 glGenFramebuffersEXT(1, &fbo_id_);
279 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_);
280
281 glGenTextures(1, &texture_id_);
282
283 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_id_);
284 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
285 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
286 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
287 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
288 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
289 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
290
291 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
292 GL_COLOR_ATTACHMENT0_EXT,
293 GL_TEXTURE_RECTANGLE_ARB,
294 texture_id_,
295 0);
296
297 // Search through the provided attributes; if the caller has
298 // requested a stencil buffer, try to get one.
299
300 int32 stencil_bits =
301 helper_->stub()->GetRequestedAttribute(EGL_STENCIL_SIZE);
302 if (stencil_bits > 0) {
303 // Create and bind the stencil buffer
304 bool has_packed_depth_stencil =
305 GLSurface::ExtensionsContain(
306 reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)),
307 "GL_EXT_packed_depth_stencil");
308
309 if (has_packed_depth_stencil) {
310 glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_id_);
311 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,
312 depth_stencil_renderbuffer_id_);
313 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
314 rounded_size_.width(), rounded_size_.height());
315 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
316 GL_STENCIL_ATTACHMENT_EXT,
317 GL_RENDERBUFFER_EXT,
318 depth_stencil_renderbuffer_id_);
319 }
320
321 // If we asked for stencil but the extension isn't present,
322 // it's OK to silently fail; subsequent code will/must check
323 // for the presence of a stencil buffer before attempting to
324 // do stencil-based operations.
325 }
326
327 bool allocated_color_buffer = storage_provider_->AllocateColorBufferStorage(
328 static_cast<CGLContextObj>(context_->GetHandle()), texture_id_,
329 rounded_size_, scale_factor_);
330 if (!allocated_color_buffer) {
331 DLOG(ERROR) << "Failed to allocate color buffer storage.";
332 DestroyFramebuffer();
333 return;
334 }
335
336 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
337 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
338 DLOG(ERROR) << "Framebuffer was incomplete: " << status;
339 DestroyFramebuffer();
340 return;
341 }
342
343 has_complete_framebuffer_ = true;
344
345 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, previous_texture_id);
346 // The FBO remains bound for this GL context.
347 }
348
349 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/image_transport_surface_fbo_mac.h ('k') | content/common/gpu/image_transport_surface_fbo_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698