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