display.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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 3// found in the LICENSE file. 4 5#include "gpu/gles2_conform_support/egl/display.h" 6 7#include <vector> 8#include "base/bind.h" 9#include "base/bind_helpers.h" 10#include "gpu/command_buffer/client/gles2_implementation.h" 11#include "gpu/command_buffer/client/gles2_lib.h" 12#include "gpu/command_buffer/client/transfer_buffer.h" 13#include "gpu/command_buffer/service/context_group.h" 14#include "gpu/command_buffer/service/transfer_buffer_manager.h" 15#include "gpu/gles2_conform_support/egl/config.h" 16#include "gpu/gles2_conform_support/egl/surface.h" 17 18namespace { 19const int32 kCommandBufferSize = 1024 * 1024; 20const int32 kTransferBufferSize = 512 * 1024; 21} 22 23namespace egl { 24 25Display::Display(EGLNativeDisplayType display_id) 26 : display_id_(display_id), 27 is_initialized_(false), 28 create_offscreen_(false), 29 create_offscreen_width_(0), 30 create_offscreen_height_(0) { 31} 32 33Display::~Display() { 34 gles2::Terminate(); 35} 36 37bool Display::Initialize() { 38 gles2::Initialize(); 39 is_initialized_ = true; 40 return true; 41} 42 43bool Display::IsValidConfig(EGLConfig config) { 44 return (config != NULL) && (config == config_.get()); 45} 46 47bool Display::ChooseConfigs(EGLConfig* configs, 48 EGLint config_size, 49 EGLint* num_config) { 50 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently 51 // does not support finding or choosing configs. 52 *num_config = 1; 53 if (configs != NULL) { 54 if (config_ == NULL) { 55 config_.reset(new Config); 56 } 57 configs[0] = config_.get(); 58 } 59 return true; 60} 61 62bool Display::GetConfigs(EGLConfig* configs, 63 EGLint config_size, 64 EGLint* num_config) { 65 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently 66 // does not support finding or choosing configs. 67 *num_config = 1; 68 if (configs != NULL) { 69 if (config_ == NULL) { 70 config_.reset(new Config); 71 } 72 configs[0] = config_.get(); 73 } 74 return true; 75} 76 77bool Display::GetConfigAttrib(EGLConfig config, 78 EGLint attribute, 79 EGLint* value) { 80 const egl::Config* cfg = static_cast<egl::Config*>(config); 81 return cfg->GetAttrib(attribute, value); 82} 83 84bool Display::IsValidNativeWindow(EGLNativeWindowType win) { 85#if defined OS_WIN 86 return ::IsWindow(win) != FALSE; 87#else 88 // TODO(alokp): Validate window handle. 89 return true; 90#endif // OS_WIN 91} 92 93bool Display::IsValidSurface(EGLSurface surface) { 94 return (surface != NULL) && (surface == surface_.get()); 95} 96 97EGLSurface Display::CreateWindowSurface(EGLConfig config, 98 EGLNativeWindowType win, 99 const EGLint* attrib_list) { 100 if (surface_ != NULL) { 101 // We do not support more than one window surface. 102 return EGL_NO_SURFACE; 103 } 104 105 { 106 gpu::TransferBufferManager* manager = new gpu::TransferBufferManager(); 107 transfer_buffer_manager_.reset(manager); 108 manager->Initialize(); 109 } 110 scoped_ptr<gpu::CommandBufferService> command_buffer( 111 new gpu::CommandBufferService(transfer_buffer_manager_.get())); 112 if (!command_buffer->Initialize()) 113 return NULL; 114 115 scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup( 116 NULL, NULL, new gpu::gles2::ShaderTranslatorCache, NULL, true)); 117 118 decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get())); 119 if (!decoder_.get()) 120 return EGL_NO_SURFACE; 121 122 gpu_scheduler_.reset(new gpu::GpuScheduler(command_buffer.get(), 123 decoder_.get(), 124 NULL)); 125 126 decoder_->set_engine(gpu_scheduler_.get()); 127 gfx::Size size(create_offscreen_width_, create_offscreen_height_); 128 if (create_offscreen_) { 129 gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size); 130 create_offscreen_ = false; 131 create_offscreen_width_ = 0; 132 create_offscreen_height_ = 0; 133 } else { 134 gl_surface_ = gfx::GLSurface::CreateViewGLSurface(win); 135 } 136 if (!gl_surface_.get()) 137 return EGL_NO_SURFACE; 138 139 gl_context_ = gfx::GLContext::CreateGLContext(NULL, 140 gl_surface_.get(), 141 gfx::PreferDiscreteGpu); 142 if (!gl_context_.get()) 143 return EGL_NO_SURFACE; 144 145 gl_context_->MakeCurrent(gl_surface_.get()); 146 147 EGLint depth_size = 0; 148 EGLint alpha_size = 0; 149 EGLint stencil_size = 0; 150 GetConfigAttrib(config, EGL_DEPTH_SIZE, &depth_size); 151 GetConfigAttrib(config, EGL_ALPHA_SIZE, &alpha_size); 152 GetConfigAttrib(config, EGL_STENCIL_SIZE, &stencil_size); 153 std::vector<int32> attribs; 154 attribs.push_back(EGL_DEPTH_SIZE); 155 attribs.push_back(depth_size); 156 attribs.push_back(EGL_ALPHA_SIZE); 157 attribs.push_back(alpha_size); 158 attribs.push_back(EGL_STENCIL_SIZE); 159 attribs.push_back(stencil_size); 160 // TODO(gman): Insert attrib_list. Although ES 1.1 says it must be null 161 attribs.push_back(EGL_NONE); 162 163 if (!decoder_->Initialize(gl_surface_.get(), 164 gl_context_.get(), 165 gl_surface_->IsOffscreen(), 166 size, 167 gpu::gles2::DisallowedFeatures(), 168 attribs)) { 169 return EGL_NO_SURFACE; 170 } 171 172 command_buffer->SetPutOffsetChangeCallback( 173 base::Bind(&gpu::GpuScheduler::PutChanged, 174 base::Unretained(gpu_scheduler_.get()))); 175 command_buffer->SetGetBufferChangeCallback( 176 base::Bind(&gpu::GpuScheduler::SetGetBuffer, 177 base::Unretained(gpu_scheduler_.get()))); 178 179 scoped_ptr<gpu::gles2::GLES2CmdHelper> cmd_helper( 180 new gpu::gles2::GLES2CmdHelper(command_buffer.get())); 181 if (!cmd_helper->Initialize(kCommandBufferSize)) 182 return NULL; 183 184 scoped_ptr<gpu::TransferBuffer> transfer_buffer(new gpu::TransferBuffer( 185 cmd_helper.get())); 186 187 command_buffer_.reset(command_buffer.release()); 188 transfer_buffer_.reset(transfer_buffer.release()); 189 gles2_cmd_helper_.reset(cmd_helper.release()); 190 surface_.reset(new Surface(win)); 191 192 return surface_.get(); 193} 194 195void Display::DestroySurface(EGLSurface surface) { 196 DCHECK(IsValidSurface(surface)); 197 gpu_scheduler_.reset(); 198 if (decoder_.get()) { 199 decoder_->Destroy(true); 200 } 201 decoder_.reset(); 202 gl_surface_ = NULL; 203 gl_context_ = NULL; 204 surface_.reset(); 205} 206 207void Display::SwapBuffers(EGLSurface surface) { 208 DCHECK(IsValidSurface(surface)); 209 context_->SwapBuffers(); 210} 211 212bool Display::IsValidContext(EGLContext ctx) { 213 return (ctx != NULL) && (ctx == context_.get()); 214} 215 216EGLContext Display::CreateContext(EGLConfig config, 217 EGLContext share_ctx, 218 const EGLint* attrib_list) { 219 DCHECK(IsValidConfig(config)); 220 // TODO(alokp): Add support for shared contexts. 221 if (share_ctx != NULL) 222 return EGL_NO_CONTEXT; 223 224 DCHECK(command_buffer_ != NULL); 225 DCHECK(transfer_buffer_.get()); 226 227 bool bind_generates_resources = true; 228 bool lose_context_when_out_of_memory = false; 229 230 context_.reset( 231 new gpu::gles2::GLES2Implementation(gles2_cmd_helper_.get(), 232 NULL, 233 transfer_buffer_.get(), 234 bind_generates_resources, 235 lose_context_when_out_of_memory, 236 this)); 237 238 if (!context_->Initialize( 239 kTransferBufferSize, 240 kTransferBufferSize / 2, 241 kTransferBufferSize * 2, 242 gpu::gles2::GLES2Implementation::kNoLimit)) { 243 return EGL_NO_CONTEXT; 244 } 245 246 context_->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets"); 247 context_->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs"); 248 249 return context_.get(); 250} 251 252void Display::DestroyContext(EGLContext ctx) { 253 DCHECK(IsValidContext(ctx)); 254 context_.reset(); 255 transfer_buffer_.reset(); 256} 257 258bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) { 259 if (ctx == EGL_NO_CONTEXT) { 260 gles2::SetGLContext(NULL); 261 } else { 262 DCHECK(IsValidSurface(draw)); 263 DCHECK(IsValidSurface(read)); 264 DCHECK(IsValidContext(ctx)); 265 gles2::SetGLContext(context_.get()); 266 } 267 return true; 268} 269 270gpu::Capabilities Display::GetCapabilities() { 271 return decoder_->GetCapabilities(); 272} 273 274gfx::GpuMemoryBuffer* Display::CreateGpuMemoryBuffer( 275 size_t width, 276 size_t height, 277 unsigned internalformat, 278 unsigned usage, 279 int32* id) { 280 NOTIMPLEMENTED(); 281 return NULL; 282} 283 284void Display::DestroyGpuMemoryBuffer(int32 id) { 285 NOTIMPLEMENTED(); 286} 287 288uint32 Display::InsertSyncPoint() { 289 NOTIMPLEMENTED(); 290 return 0u; 291} 292 293uint32 Display::InsertFutureSyncPoint() { 294 NOTIMPLEMENTED(); 295 return 0u; 296} 297 298void Display::RetireSyncPoint(uint32 sync_point) { 299 NOTIMPLEMENTED(); 300} 301 302void Display::SignalSyncPoint(uint32 sync_point, 303 const base::Closure& callback) { 304 NOTIMPLEMENTED(); 305} 306 307void Display::SignalQuery(uint32 query, const base::Closure& callback) { 308 NOTIMPLEMENTED(); 309} 310 311void Display::SetSurfaceVisible(bool visible) { 312 NOTIMPLEMENTED(); 313} 314 315void Display::Echo(const base::Closure& callback) { 316 NOTIMPLEMENTED(); 317} 318 319uint32 Display::CreateStreamTexture(uint32 texture_id) { 320 NOTIMPLEMENTED(); 321 return 0; 322} 323 324} // namespace egl 325