Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/common/gpu/texture_image_transport_surface.h" | 5 #include "content/common/gpu/texture_image_transport_surface.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "content/common/gpu/gpu_channel.h" | 11 #include "content/common/gpu/gpu_channel.h" |
| 12 #include "content/common/gpu/gpu_channel_manager.h" | 12 #include "content/common/gpu/gpu_channel_manager.h" |
| 13 #include "content/common/gpu/gpu_messages.h" | 13 #include "content/common/gpu/gpu_messages.h" |
| 14 #include "content/common/gpu/sync_point_manager.h" | 14 #include "content/common/gpu/sync_point_manager.h" |
| 15 #include "content/public/common/content_switches.h" | 15 #include "content/public/common/content_switches.h" |
| 16 #include "gpu/command_buffer/service/context_group.h" | 16 #include "gpu/command_buffer/service/context_group.h" |
| 17 #include "gpu/command_buffer/service/gpu_scheduler.h" | 17 #include "gpu/command_buffer/service/gpu_scheduler.h" |
| 18 #include "ui/gl/scoped_binders.h" | 18 #include "ui/gl/scoped_binders.h" |
| 19 | 19 |
| 20 using gpu::gles2::ContextGroup; | 20 using gpu::gles2::ContextGroup; |
| 21 using gpu::gles2::GLES2Decoder; | |
| 21 using gpu::gles2::MailboxManager; | 22 using gpu::gles2::MailboxManager; |
| 22 using gpu::gles2::MailboxName; | 23 using gpu::gles2::MailboxName; |
| 23 using gpu::gles2::TextureDefinition; | 24 using gpu::gles2::Texture; |
| 24 using gpu::gles2::TextureManager; | 25 using gpu::gles2::TextureManager; |
| 26 using gpu::gles2::TextureRef; | |
| 25 | 27 |
| 26 namespace content { | 28 namespace content { |
| 27 | 29 |
| 28 TextureImageTransportSurface::TextureImageTransportSurface( | 30 TextureImageTransportSurface::TextureImageTransportSurface( |
| 29 GpuChannelManager* manager, | 31 GpuChannelManager* manager, |
| 30 GpuCommandBufferStub* stub, | 32 GpuCommandBufferStub* stub, |
| 31 const gfx::GLSurfaceHandle& handle) | 33 const gfx::GLSurfaceHandle& handle) |
| 32 : fbo_id_(0), | 34 : fbo_id_(0), |
| 33 backbuffer_(CreateTextureDefinition(gfx::Size(), 0)), | 35 current_size_(1, 1), |
| 34 stub_destroyed_(false), | 36 stub_destroyed_(false), |
| 35 backbuffer_suggested_allocation_(true), | 37 backbuffer_suggested_allocation_(true), |
| 36 frontbuffer_suggested_allocation_(true), | 38 frontbuffer_suggested_allocation_(true), |
| 37 handle_(handle), | 39 handle_(handle), |
| 38 is_swap_buffers_pending_(false), | 40 is_swap_buffers_pending_(false), |
| 39 did_unschedule_(false) { | 41 did_unschedule_(false) { |
| 40 helper_.reset(new ImageTransportHelper(this, | 42 helper_.reset(new ImageTransportHelper(this, |
| 41 manager, | 43 manager, |
| 42 stub, | 44 stub, |
| 43 gfx::kNullPluginWindow)); | 45 gfx::kNullPluginWindow)); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 // Ack arrives. | 86 // Ack arrives. |
| 85 DCHECK(!did_unschedule_); | 87 DCHECK(!did_unschedule_); |
| 86 if (is_swap_buffers_pending_) { | 88 if (is_swap_buffers_pending_) { |
| 87 did_unschedule_ = true; | 89 did_unschedule_ = true; |
| 88 helper_->SetScheduled(false); | 90 helper_->SetScheduled(false); |
| 89 return true; | 91 return true; |
| 90 } | 92 } |
| 91 return false; | 93 return false; |
| 92 } | 94 } |
| 93 | 95 |
| 94 bool TextureImageTransportSurface::Resize(const gfx::Size&) { | |
| 95 return true; | |
| 96 } | |
| 97 | |
| 98 bool TextureImageTransportSurface::IsOffscreen() { | 96 bool TextureImageTransportSurface::IsOffscreen() { |
| 99 return true; | 97 return true; |
| 100 } | 98 } |
| 101 | 99 |
| 102 bool TextureImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { | 100 unsigned int TextureImageTransportSurface::GetBackingFrameBufferObject() { |
| 103 if (stub_destroyed_) { | |
| 104 // Early-exit so that we don't recreate the fbo. We still want to return | |
| 105 // true, so that the context is made current and the GLES2DecoderImpl can | |
| 106 // release its own resources. | |
| 107 return true; | |
| 108 } | |
| 109 | |
| 110 context_ = context; | |
| 111 | |
| 112 if (!fbo_id_) { | 101 if (!fbo_id_) { |
| 113 glGenFramebuffersEXT(1, &fbo_id_); | 102 glGenFramebuffersEXT(1, &fbo_id_); |
| 114 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_); | 103 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_); |
| 115 current_size_ = gfx::Size(1, 1); | |
| 116 helper_->stub()->AddDestructionObserver(this); | 104 helper_->stub()->AddDestructionObserver(this); |
| 105 CreateBackTexture(); | |
| 117 } | 106 } |
| 118 | 107 |
| 119 // We could be receiving non-deferred GL commands, that is anything that does | |
| 120 // not need a framebuffer. | |
| 121 if (!backbuffer_->service_id() && !is_swap_buffers_pending_ && | |
| 122 backbuffer_suggested_allocation_) { | |
| 123 CreateBackTexture(); | |
|
piman
2013/05/23 02:33:01
note: Construction moved to GetBackingFrameBufferO
| |
| 124 } | |
| 125 return true; | |
| 126 } | |
| 127 | |
| 128 unsigned int TextureImageTransportSurface::GetBackingFrameBufferObject() { | |
| 129 return fbo_id_; | 108 return fbo_id_; |
| 130 } | 109 } |
| 131 | 110 |
| 132 bool TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { | 111 bool TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { |
| 133 DCHECK(!is_swap_buffers_pending_); | 112 DCHECK(!is_swap_buffers_pending_); |
| 134 if (backbuffer_suggested_allocation_ == allocation) | 113 if (backbuffer_suggested_allocation_ == allocation) |
| 135 return true; | 114 return true; |
| 136 backbuffer_suggested_allocation_ = allocation; | 115 backbuffer_suggested_allocation_ = allocation; |
| 137 | 116 |
| 138 if (backbuffer_suggested_allocation_) { | 117 if (backbuffer_suggested_allocation_) { |
| 139 DCHECK(!backbuffer_->service_id()); | 118 DCHECK(!backbuffer_); |
| 140 CreateBackTexture(); | 119 CreateBackTexture(); |
| 141 } else { | 120 } else { |
| 142 ReleaseBackTexture(); | 121 ReleaseBackTexture(); |
| 143 } | 122 } |
| 144 | 123 |
| 145 return true; | 124 return true; |
| 146 } | 125 } |
| 147 | 126 |
| 148 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { | 127 void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { |
| 149 if (frontbuffer_suggested_allocation_ == allocation) | 128 if (frontbuffer_suggested_allocation_ == allocation) |
| 150 return; | 129 return; |
| 151 frontbuffer_suggested_allocation_ = allocation; | 130 frontbuffer_suggested_allocation_ = allocation; |
| 152 | 131 |
| 153 if (!frontbuffer_suggested_allocation_) { | 132 // If a swapbuffers is in flight, wait for the ack before releasing the front |
| 154 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | 133 // buffer: |
| 155 helper_->SendAcceleratedSurfaceRelease(params); | 134 // - we don't know yet which texture the browser will want to keep |
| 135 // - we want to ensure we don't destroy a texture that is in flight before the | |
| 136 // browser got a reference on it. | |
| 137 if (!frontbuffer_suggested_allocation_ && | |
| 138 !is_swap_buffers_pending_ && | |
| 139 helper_->MakeCurrent()) { | |
| 140 ReleaseFrontTexture(); | |
| 156 } | 141 } |
| 157 } | 142 } |
| 158 | 143 |
| 159 void* TextureImageTransportSurface::GetShareHandle() { | 144 void* TextureImageTransportSurface::GetShareHandle() { |
| 160 return GetHandle(); | 145 return GetHandle(); |
| 161 } | 146 } |
| 162 | 147 |
| 163 void* TextureImageTransportSurface::GetDisplay() { | 148 void* TextureImageTransportSurface::GetDisplay() { |
| 164 return surface_.get() ? surface_->GetDisplay() : NULL; | 149 return surface_.get() ? surface_->GetDisplay() : NULL; |
| 165 } | 150 } |
| 166 | 151 |
| 167 void* TextureImageTransportSurface::GetConfig() { | 152 void* TextureImageTransportSurface::GetConfig() { |
| 168 return surface_.get() ? surface_->GetConfig() : NULL; | 153 return surface_.get() ? surface_->GetConfig() : NULL; |
| 169 } | 154 } |
| 170 | 155 |
| 171 void TextureImageTransportSurface::OnResize(gfx::Size size) { | 156 void TextureImageTransportSurface::OnResize(gfx::Size size) { |
| 157 DCHECK_GE(size.width(), 1); | |
| 158 DCHECK_GE(size.height(), 1); | |
| 172 current_size_ = size; | 159 current_size_ = size; |
| 173 CreateBackTexture(); | 160 CreateBackTexture(); |
| 174 } | 161 } |
| 175 | 162 |
| 176 void TextureImageTransportSurface::OnWillDestroyStub() { | 163 void TextureImageTransportSurface::OnWillDestroyStub() { |
| 177 helper_->stub()->RemoveDestructionObserver(this); | 164 helper_->stub()->RemoveDestructionObserver(this); |
| 178 | 165 |
| 179 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | |
| 180 helper_->SendAcceleratedSurfaceRelease(params); | |
| 181 | |
| 182 ReleaseBackTexture(); | |
| 183 | |
| 184 // We are losing the stub owning us, this is our last chance to clean up the | 166 // We are losing the stub owning us, this is our last chance to clean up the |
| 185 // resources we allocated in the stub's context. | 167 // resources we allocated in the stub's context. |
| 168 ReleaseBackTexture(); | |
| 169 ReleaseFrontTexture(); | |
| 170 | |
| 186 if (fbo_id_) { | 171 if (fbo_id_) { |
| 187 glDeleteFramebuffersEXT(1, &fbo_id_); | 172 glDeleteFramebuffersEXT(1, &fbo_id_); |
| 188 CHECK_GL_ERROR(); | 173 CHECK_GL_ERROR(); |
| 189 fbo_id_ = 0; | 174 fbo_id_ = 0; |
| 190 } | 175 } |
| 191 | 176 |
| 192 stub_destroyed_ = true; | 177 stub_destroyed_ = true; |
| 193 } | 178 } |
| 194 | 179 |
| 195 void TextureImageTransportSurface::SetLatencyInfo( | 180 void TextureImageTransportSurface::SetLatencyInfo( |
| 196 const cc::LatencyInfo& latency_info) { | 181 const cc::LatencyInfo& latency_info) { |
| 197 latency_info_ = latency_info; | 182 latency_info_ = latency_info; |
| 198 } | 183 } |
| 199 | 184 |
| 200 bool TextureImageTransportSurface::SwapBuffers() { | 185 bool TextureImageTransportSurface::SwapBuffers() { |
| 201 DCHECK(backbuffer_suggested_allocation_); | 186 DCHECK(backbuffer_suggested_allocation_); |
| 202 | 187 |
| 203 if (!frontbuffer_suggested_allocation_) | 188 if (!frontbuffer_suggested_allocation_) |
| 204 return true; | 189 return true; |
| 205 | 190 |
| 206 if (!backbuffer_->service_id()) { | 191 if (!backbuffer_) { |
| 207 LOG(ERROR) << "Swap without valid backing."; | 192 LOG(ERROR) << "Swap without valid backing."; |
| 208 return true; | 193 return true; |
| 209 } | 194 } |
| 210 | 195 |
| 211 DCHECK(backbuffer_size() == current_size_); | 196 DCHECK(backbuffer_size() == current_size_); |
| 212 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; | 197 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; |
| 213 params.size = backbuffer_size(); | 198 params.size = backbuffer_size(); |
| 214 params.mailbox_name.assign( | 199 params.mailbox_name.assign( |
| 215 reinterpret_cast<const char*>(&mailbox_name_), sizeof(mailbox_name_)); | 200 reinterpret_cast<const char*>(&back_mailbox_name_), |
| 201 sizeof(back_mailbox_name_)); | |
| 216 | 202 |
| 217 glFlush(); | 203 glFlush(); |
|
greggman
2013/05/23 17:36:19
This is probably a dumb question since I'm not cle
piman
2013/05/23 18:02:38
SwapBuffers and SetBackbufferAllocation are called
piman
2013/05/24 02:32:22
Added a bunch of DCHECKs in functions that call GL
| |
| 218 ProduceTexture(); | |
| 219 | |
| 220 // Do not allow destruction while we are still waiting for a swap ACK, | |
| 221 // so we do not leak a texture in the mailbox. | |
| 222 AddRef(); | |
| 223 | 204 |
| 224 params.latency_info = latency_info_; | 205 params.latency_info = latency_info_; |
| 225 helper_->SendAcceleratedSurfaceBuffersSwapped(params); | 206 helper_->SendAcceleratedSurfaceBuffersSwapped(params); |
| 226 | 207 |
| 227 DCHECK(!is_swap_buffers_pending_); | 208 DCHECK(!is_swap_buffers_pending_); |
| 228 is_swap_buffers_pending_ = true; | 209 is_swap_buffers_pending_ = true; |
| 229 return true; | 210 return true; |
| 230 } | 211 } |
| 231 | 212 |
| 232 bool TextureImageTransportSurface::PostSubBuffer( | 213 bool TextureImageTransportSurface::PostSubBuffer( |
| 233 int x, int y, int width, int height) { | 214 int x, int y, int width, int height) { |
| 234 DCHECK(backbuffer_suggested_allocation_); | 215 DCHECK(backbuffer_suggested_allocation_); |
| 235 if (!frontbuffer_suggested_allocation_) | 216 if (!frontbuffer_suggested_allocation_) |
| 236 return true; | 217 return true; |
| 237 const gfx::Rect new_damage_rect(x, y, width, height); | 218 const gfx::Rect new_damage_rect(x, y, width, height); |
| 238 DCHECK(gfx::Rect(gfx::Point(), current_size_).Contains(new_damage_rect)); | 219 DCHECK(gfx::Rect(gfx::Point(), current_size_).Contains(new_damage_rect)); |
| 239 | 220 |
| 240 // An empty damage rect is a successful no-op. | 221 // An empty damage rect is a successful no-op. |
| 241 if (new_damage_rect.IsEmpty()) | 222 if (new_damage_rect.IsEmpty()) |
| 242 return true; | 223 return true; |
| 243 | 224 |
| 244 if (!backbuffer_->service_id()) { | 225 if (!backbuffer_) { |
| 245 LOG(ERROR) << "Swap without valid backing."; | 226 LOG(ERROR) << "Swap without valid backing."; |
| 246 return true; | 227 return true; |
| 247 } | 228 } |
| 248 | 229 |
| 249 DCHECK(current_size_ == backbuffer_size()); | 230 DCHECK(current_size_ == backbuffer_size()); |
| 250 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; | 231 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; |
| 251 params.surface_size = backbuffer_size(); | 232 params.surface_size = backbuffer_size(); |
| 252 params.x = x; | 233 params.x = x; |
| 253 params.y = y; | 234 params.y = y; |
| 254 params.width = width; | 235 params.width = width; |
| 255 params.height = height; | 236 params.height = height; |
| 256 params.mailbox_name.assign( | 237 params.mailbox_name.assign( |
| 257 reinterpret_cast<const char*>(&mailbox_name_), sizeof(mailbox_name_)); | 238 reinterpret_cast<const char*>(&back_mailbox_name_), |
| 239 sizeof(back_mailbox_name_)); | |
| 258 | 240 |
| 259 glFlush(); | 241 glFlush(); |
| 260 ProduceTexture(); | |
| 261 | |
| 262 // Do not allow destruction while we are still waiting for a swap ACK, | |
| 263 // so we do not leak a texture in the mailbox. | |
| 264 AddRef(); | |
| 265 | 242 |
| 266 params.latency_info = latency_info_; | 243 params.latency_info = latency_info_; |
| 267 helper_->SendAcceleratedSurfacePostSubBuffer(params); | 244 helper_->SendAcceleratedSurfacePostSubBuffer(params); |
| 268 | 245 |
| 269 DCHECK(!is_swap_buffers_pending_); | 246 DCHECK(!is_swap_buffers_pending_); |
| 270 is_swap_buffers_pending_ = true; | 247 is_swap_buffers_pending_ = true; |
| 271 return true; | 248 return true; |
| 272 } | 249 } |
| 273 | 250 |
| 274 std::string TextureImageTransportSurface::GetExtensions() { | 251 std::string TextureImageTransportSurface::GetExtensions() { |
| 275 std::string extensions = gfx::GLSurface::GetExtensions(); | 252 std::string extensions = gfx::GLSurface::GetExtensions(); |
| 276 extensions += extensions.empty() ? "" : " "; | 253 extensions += extensions.empty() ? "" : " "; |
| 277 extensions += "GL_CHROMIUM_front_buffer_cached "; | 254 extensions += "GL_CHROMIUM_front_buffer_cached "; |
| 278 extensions += "GL_CHROMIUM_post_sub_buffer"; | 255 extensions += "GL_CHROMIUM_post_sub_buffer"; |
| 279 return extensions; | 256 return extensions; |
| 280 } | 257 } |
| 281 | 258 |
| 282 gfx::Size TextureImageTransportSurface::GetSize() { | 259 gfx::Size TextureImageTransportSurface::GetSize() { |
| 283 gfx::Size size = current_size_; | 260 return current_size_; |
| 284 | |
| 285 // OSMesa expects a non-zero size. | |
| 286 return gfx::Size(size.width() == 0 ? 1 : size.width(), | |
| 287 size.height() == 0 ? 1 : size.height()); | |
| 288 } | 261 } |
| 289 | 262 |
| 290 void* TextureImageTransportSurface::GetHandle() { | 263 void* TextureImageTransportSurface::GetHandle() { |
| 291 return surface_.get() ? surface_->GetHandle() : NULL; | 264 return surface_.get() ? surface_->GetHandle() : NULL; |
| 292 } | 265 } |
| 293 | 266 |
| 294 unsigned TextureImageTransportSurface::GetFormat() { | 267 unsigned TextureImageTransportSurface::GetFormat() { |
| 295 return surface_.get() ? surface_->GetFormat() : 0; | 268 return surface_.get() ? surface_->GetFormat() : 0; |
| 296 } | 269 } |
| 297 | 270 |
| 298 void TextureImageTransportSurface::OnBufferPresented( | 271 void TextureImageTransportSurface::OnBufferPresented( |
| 299 const AcceleratedSurfaceMsg_BufferPresented_Params& params) { | 272 const AcceleratedSurfaceMsg_BufferPresented_Params& params) { |
| 300 if (params.sync_point == 0) { | 273 if (params.sync_point == 0) { |
| 301 BufferPresentedImpl(params.mailbox_name); | 274 BufferPresentedImpl(params.mailbox_name); |
| 302 } else { | 275 } else { |
| 303 helper_->manager()->sync_point_manager()->AddSyncPointCallback( | 276 helper_->manager()->sync_point_manager()->AddSyncPointCallback( |
| 304 params.sync_point, | 277 params.sync_point, |
| 305 base::Bind(&TextureImageTransportSurface::BufferPresentedImpl, | 278 base::Bind(&TextureImageTransportSurface::BufferPresentedImpl, |
| 306 this, | 279 this, |
| 307 params.mailbox_name)); | 280 params.mailbox_name)); |
| 308 } | 281 } |
| 309 | |
| 310 // Careful, we might get deleted now if we were only waiting for | |
| 311 // a final swap ACK. | |
| 312 Release(); | |
| 313 } | 282 } |
| 314 | 283 |
| 315 void TextureImageTransportSurface::BufferPresentedImpl( | 284 void TextureImageTransportSurface::BufferPresentedImpl( |
| 316 const std::string& mailbox_name) { | 285 const std::string& mailbox_name) { |
| 317 DCHECK(!backbuffer_->service_id()); | 286 bool swap = true; |
| 318 if (!mailbox_name.empty()) { | 287 if (backbuffer_ && !mailbox_name.empty()) { |
|
no sievers
2013/05/24 01:31:38
When would backbuffer_ ever be invalid here?
We ca
piman
2013/05/24 02:32:22
I can't remember why I did this originally (I had
| |
| 319 DCHECK(mailbox_name.length() == GL_MAILBOX_SIZE_CHROMIUM); | 288 DCHECK(mailbox_name.length() == GL_MAILBOX_SIZE_CHROMIUM); |
| 320 mailbox_name.copy(reinterpret_cast<char *>(&mailbox_name_), | 289 |
| 321 sizeof(MailboxName)); | 290 MailboxName name; |
| 322 ConsumeTexture(); | 291 mailbox_name.copy(reinterpret_cast<char *>(&name), sizeof(MailboxName)); |
| 292 if (!memcmp(&name, &back_mailbox_name_, sizeof(name))) | |
|
no sievers
2013/05/24 01:31:38
nit: maybe comment that the browser skipped/return
piman
2013/05/24 02:32:22
Done. (also simplified a bit, I don't need to copy
| |
| 293 swap = false; | |
| 323 } | 294 } |
| 324 | 295 if (swap) { |
| 325 if (stub_destroyed_ && backbuffer_->service_id()) { | 296 std::swap(backbuffer_, frontbuffer_); |
| 326 // TODO(sievers): Remove this after changes to the mailbox to take ownership | 297 std::swap(back_mailbox_name_, front_mailbox_name_); |
| 327 // of the service ids. | |
| 328 DCHECK(context_.get() && surface_.get()); | |
| 329 uint32 service_id = backbuffer_->ReleaseServiceId(); | |
| 330 if (context_->MakeCurrent(surface_)) | |
| 331 glDeleteTextures(1, &service_id); | |
| 332 | |
| 333 return; | |
| 334 } | 298 } |
| 335 | 299 |
| 336 DCHECK(is_swap_buffers_pending_); | 300 DCHECK(is_swap_buffers_pending_); |
| 337 is_swap_buffers_pending_ = false; | 301 is_swap_buffers_pending_ = false; |
| 338 | 302 |
| 339 // We should not have allowed the backbuffer to be discarded while the ack | 303 // We should not have allowed the backbuffer to be discarded while the ack |
| 340 // was pending. | 304 // was pending. |
| 341 DCHECK(backbuffer_suggested_allocation_); | 305 DCHECK(backbuffer_suggested_allocation_); |
| 342 | 306 |
| 343 // We're relying on the fact that the parent context is | 307 // We're relying on the fact that the parent context is |
| 344 // finished with it's context when it inserts the sync point that | 308 // finished with its context when it inserts the sync point that |
| 345 // triggers this callback. | 309 // triggers this callback. |
| 346 if (helper_->MakeCurrent()) { | 310 if (helper_->MakeCurrent()) { |
| 347 if (backbuffer_size() != current_size_ || !backbuffer_->service_id()) | 311 if (frontbuffer_ && !frontbuffer_suggested_allocation_) |
| 312 ReleaseFrontTexture(); | |
| 313 if (!backbuffer_ || backbuffer_size() != current_size_) | |
| 348 CreateBackTexture(); | 314 CreateBackTexture(); |
| 349 else | 315 else |
| 350 AttachBackTextureToFBO(); | 316 AttachBackTextureToFBO(); |
| 351 } | 317 } |
| 352 | 318 |
| 353 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context | 319 // Even if MakeCurrent fails, schedule anyway, to trigger the lost context |
| 354 // logic. | 320 // logic. |
| 355 if (did_unschedule_) { | 321 if (did_unschedule_) { |
| 356 did_unschedule_ = false; | 322 did_unschedule_ = false; |
| 357 helper_->SetScheduled(true); | 323 helper_->SetScheduled(true); |
| 358 } | 324 } |
| 359 } | 325 } |
| 360 | 326 |
| 361 void TextureImageTransportSurface::OnResizeViewACK() { | 327 void TextureImageTransportSurface::OnResizeViewACK() { |
| 362 NOTREACHED(); | 328 NOTREACHED(); |
| 363 } | 329 } |
| 364 | 330 |
| 365 void TextureImageTransportSurface::ReleaseBackTexture() { | 331 void TextureImageTransportSurface::ReleaseBackTexture() { |
| 366 if (!backbuffer_->service_id()) | 332 backbuffer_ = NULL; |
| 367 return; | 333 back_mailbox_name_ = MailboxName(); |
| 368 | |
| 369 uint32 service_id = backbuffer_->ReleaseServiceId(); | |
| 370 glDeleteTextures(1, &service_id); | |
| 371 backbuffer_.reset(CreateTextureDefinition(gfx::Size(), 0)); | |
| 372 mailbox_name_ = MailboxName(); | |
| 373 glFlush(); | 334 glFlush(); |
| 374 CHECK_GL_ERROR(); | 335 CHECK_GL_ERROR(); |
| 375 } | 336 } |
| 376 | 337 |
| 338 void TextureImageTransportSurface::ReleaseFrontTexture() { | |
| 339 frontbuffer_ = NULL; | |
| 340 front_mailbox_name_ = MailboxName(); | |
| 341 glFlush(); | |
| 342 CHECK_GL_ERROR(); | |
| 343 GpuHostMsg_AcceleratedSurfaceRelease_Params params; | |
| 344 helper_->SendAcceleratedSurfaceRelease(params); | |
| 345 } | |
| 346 | |
| 377 void TextureImageTransportSurface::CreateBackTexture() { | 347 void TextureImageTransportSurface::CreateBackTexture() { |
| 378 // If |is_swap_buffers_pending| we are waiting for our backbuffer | 348 // If |is_swap_buffers_pending| we are waiting for our backbuffer |
| 379 // in the mailbox, so we shouldn't be reallocating it now. | 349 // in the mailbox, so we shouldn't be reallocating it now. |
| 380 DCHECK(!is_swap_buffers_pending_); | 350 DCHECK(!is_swap_buffers_pending_); |
| 381 | 351 |
| 382 if (backbuffer_->service_id() && backbuffer_size() == current_size_) | 352 if (backbuffer_ && backbuffer_size() == current_size_) |
| 383 return; | 353 return; |
| 384 | 354 |
| 385 uint32 service_id = backbuffer_->ReleaseServiceId(); | |
| 386 | |
| 387 VLOG(1) << "Allocating new backbuffer texture"; | 355 VLOG(1) << "Allocating new backbuffer texture"; |
| 388 | 356 |
| 389 // On Qualcomm we couldn't resize an FBO texture past a certain | 357 // On Qualcomm we couldn't resize an FBO texture past a certain |
| 390 // size, after we allocated it as 1x1. So here we simply delete | 358 // size, after we allocated it as 1x1. So here we simply delete |
| 391 // the previous texture on resize, to insure we don't 'run out of | 359 // the previous texture on resize, to insure we don't 'run out of |
| 392 // memory'. | 360 // memory'. |
| 393 if (service_id && | 361 if (backbuffer_ && |
| 394 helper_->stub() | 362 helper_->stub() |
| 395 ->decoder() | 363 ->decoder() |
| 396 ->GetContextGroup() | 364 ->GetContextGroup() |
| 397 ->feature_info() | 365 ->feature_info() |
| 398 ->workarounds() | 366 ->workarounds() |
| 399 .delete_instead_of_resize_fbo) { | 367 .delete_instead_of_resize_fbo) { |
| 400 glDeleteTextures(1, &service_id); | 368 ReleaseBackTexture(); |
| 401 service_id = 0; | 369 } |
| 402 mailbox_name_ = MailboxName(); | 370 GLES2Decoder* decoder = helper_->stub()->decoder(); |
| 371 TextureManager* texture_manager = | |
| 372 decoder->GetContextGroup()->texture_manager(); | |
| 373 if (!backbuffer_) { | |
| 374 mailbox_manager_->GenerateMailboxName(&back_mailbox_name_); | |
| 375 GLuint service_id; | |
| 376 glGenTextures(1, &service_id); | |
| 377 backbuffer_ = TextureRef::Create(texture_manager, 0, service_id); | |
| 378 texture_manager->SetTarget(backbuffer_, GL_TEXTURE_2D); | |
| 379 Texture* texture = texture_manager->Produce(backbuffer_); | |
| 380 bool success = mailbox_manager_->ProduceTexture( | |
| 381 GL_TEXTURE_2D, back_mailbox_name_, texture); | |
| 382 DCHECK(success); | |
| 403 } | 383 } |
| 404 | 384 |
| 405 if (!service_id) { | |
| 406 MailboxName new_mailbox_name; | |
| 407 MailboxName& name = mailbox_name_; | |
| 408 // This slot should be uninitialized. | |
| 409 DCHECK(!memcmp(&name, &new_mailbox_name, sizeof(MailboxName))); | |
| 410 mailbox_manager_->GenerateMailboxName(&new_mailbox_name); | |
| 411 name = new_mailbox_name; | |
| 412 glGenTextures(1, &service_id); | |
| 413 } | |
| 414 | |
| 415 backbuffer_.reset( | |
| 416 CreateTextureDefinition(current_size_, service_id)); | |
| 417 | |
| 418 { | 385 { |
| 419 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, service_id); | 386 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, |
| 420 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 387 backbuffer_->service_id()); |
| 421 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
| 422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 423 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 424 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, | 388 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, |
| 425 current_size_.width(), current_size_.height(), 0, | 389 current_size_.width(), current_size_.height(), 0, |
| 426 GL_RGBA, GL_UNSIGNED_BYTE, NULL); | 390 GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
| 391 gpu::gles2::ErrorState* error_state = decoder->GetErrorState(); | |
| 392 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, | |
| 393 GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
| 394 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, | |
| 395 GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
| 396 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, | |
| 397 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 398 texture_manager->SetParameter("Backbuffer", error_state, backbuffer_, | |
| 399 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 400 texture_manager->SetLevelInfo( | |
| 401 backbuffer_, | |
| 402 GL_TEXTURE_2D, | |
| 403 0, | |
| 404 GL_RGBA, | |
| 405 current_size_.width(), | |
| 406 current_size_.height(), | |
| 407 1, | |
| 408 0, | |
| 409 GL_RGBA, | |
| 410 GL_UNSIGNED_BYTE, | |
| 411 true); | |
| 412 DCHECK(texture_manager->CanRender(backbuffer_)); | |
| 427 CHECK_GL_ERROR(); | 413 CHECK_GL_ERROR(); |
| 428 } | 414 } |
| 429 | 415 |
| 430 AttachBackTextureToFBO(); | 416 AttachBackTextureToFBO(); |
| 431 } | 417 } |
| 432 | 418 |
| 433 void TextureImageTransportSurface::AttachBackTextureToFBO() { | 419 void TextureImageTransportSurface::AttachBackTextureToFBO() { |
| 434 DCHECK(backbuffer_->service_id()); | 420 DCHECK(backbuffer_->service_id()); |
| 435 gfx::ScopedFrameBufferBinder fbo_binder(fbo_id_); | 421 gfx::ScopedFrameBufferBinder fbo_binder(fbo_id_); |
| 436 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, | 422 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, |
| 437 GL_COLOR_ATTACHMENT0, | 423 GL_COLOR_ATTACHMENT0, |
| 438 GL_TEXTURE_2D, | 424 GL_TEXTURE_2D, |
| 439 backbuffer_->service_id(), | 425 backbuffer_->service_id(), |
| 440 0); | 426 0); |
| 441 CHECK_GL_ERROR(); | 427 CHECK_GL_ERROR(); |
| 442 | 428 |
| 443 #ifndef NDEBUG | 429 #ifndef NDEBUG |
| 444 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); | 430 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); |
| 445 if (status != GL_FRAMEBUFFER_COMPLETE) { | 431 if (status != GL_FRAMEBUFFER_COMPLETE) { |
| 446 DLOG(FATAL) << "Framebuffer incomplete: " << status; | 432 DLOG(FATAL) << "Framebuffer incomplete: " << status; |
| 447 } | 433 } |
| 448 #endif | 434 #endif |
| 449 } | 435 } |
| 450 | 436 |
| 451 TextureDefinition* TextureImageTransportSurface::CreateTextureDefinition( | |
| 452 gfx::Size size, int service_id) { | |
| 453 TextureDefinition::LevelInfo info( | |
| 454 GL_TEXTURE_2D, GL_RGBA, size.width(), size.height(), 1, | |
| 455 0, GL_RGBA, GL_UNSIGNED_BYTE, true); | |
| 456 | |
| 457 TextureDefinition::LevelInfos level_infos; | |
| 458 level_infos.resize(1); | |
| 459 level_infos[0].resize(1); | |
| 460 level_infos[0][0] = info; | |
| 461 return new TextureDefinition( | |
| 462 GL_TEXTURE_2D, | |
| 463 service_id, | |
| 464 GL_LINEAR, | |
| 465 GL_LINEAR, | |
| 466 GL_CLAMP_TO_EDGE, | |
| 467 GL_CLAMP_TO_EDGE, | |
| 468 GL_NONE, | |
| 469 true, | |
| 470 false, | |
| 471 level_infos); | |
| 472 } | |
| 473 | |
| 474 void TextureImageTransportSurface::ConsumeTexture() { | |
| 475 DCHECK(!backbuffer_->service_id()); | |
| 476 | |
| 477 backbuffer_.reset(mailbox_manager_->ConsumeTexture( | |
| 478 GL_TEXTURE_2D, mailbox_name_)); | |
| 479 if (!backbuffer_) { | |
| 480 mailbox_name_ = MailboxName(); | |
| 481 backbuffer_.reset(CreateTextureDefinition(gfx::Size(), 0)); | |
| 482 } | |
| 483 } | |
| 484 | |
| 485 void TextureImageTransportSurface::ProduceTexture() { | |
| 486 DCHECK(backbuffer_->service_id()); | |
| 487 DCHECK(!backbuffer_size().IsEmpty()); | |
| 488 | |
| 489 // Pass NULL as |owner| here to avoid errors from glConsumeTextureCHROMIUM() | |
| 490 // when the renderer context group goes away before the RWHV handles a pending | |
| 491 // ACK. We avoid leaking a texture in the mailbox by waiting for the final ACK | |
| 492 // at which point we consume the correct texture back. | |
| 493 bool success = mailbox_manager_->ProduceTexture( | |
| 494 GL_TEXTURE_2D, | |
| 495 mailbox_name_, | |
| 496 backbuffer_.release(), | |
| 497 NULL); | |
| 498 DCHECK(success); | |
| 499 mailbox_name_ = MailboxName(); | |
| 500 backbuffer_.reset(CreateTextureDefinition(gfx::Size(), 0)); | |
| 501 } | |
| 502 | |
| 503 } // namespace content | 437 } // namespace content |
| OLD | NEW |