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