summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer
diff options
context:
space:
mode:
authorapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-05 21:53:50 +0000
committerapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-05 21:53:50 +0000
commit246a7045b9c45620fd725210aac51322e611c83f (patch)
tree6bdce605ae758c282a2b27e92a6b223d98b8d46a /gpu/command_buffer
parentc3240722a63ff142684575e3ea4eb89915edae72 (diff)
downloadchromium_src-246a7045b9c45620fd725210aac51322e611c83f.zip
chromium_src-246a7045b9c45620fd725210aac51322e611c83f.tar.gz
chromium_src-246a7045b9c45620fd725210aac51322e611c83f.tar.bz2
Added support for opening a GPU command buffer from a renderer processes through a GPU channel.
Probably only works in windows only so far. TEST=none BUG=none Review URL: http://codereview.chromium.org/657046 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40783 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer')
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc235
-rw-r--r--gpu/command_buffer/service/gpu_processor_win.cc8
2 files changed, 156 insertions, 87 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index dbb49e9..e07dc99 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -287,8 +287,14 @@ class GLES2DecoderImpl : public GLES2Decoder {
return group_->texture_manager();
}
+#if defined(OS_WIN)
+ static bool InitializeOneOff(bool anti_aliased);
+#endif
+
+
bool InitPlatformSpecific();
- bool InitGlew();
+ static bool InitGlew();
+ void DestroyPlatformSpecific();
// Template to help call glGenXXX functions.
template <void gl_gen_function(GLES2DecoderImpl*, GLsizei, GLuint*)>
@@ -615,8 +621,10 @@ class GLES2DecoderImpl : public GLES2Decoder {
#if defined(UNIT_TEST)
#elif defined(OS_WIN)
- HDC device_context_;
+ static int pixel_format_;
+ HDC gl_device_context_;
HGLRC gl_context_;
+ HPBUFFERARB pbuffer_;
#elif defined(OS_MACOSX)
CGLContextObj gl_context_;
CGLPBufferObj pbuffer_;
@@ -657,6 +665,11 @@ GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
return new GLES2DecoderImpl(group);
}
+#if defined(UNIT_TEST)
+#elif defined(OS_WIN)
+int GLES2DecoderImpl::pixel_format_;
+#endif
+
GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
: GLES2Decoder(group),
error_bits_(0),
@@ -668,8 +681,9 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
black_cube_texture_id_(0),
#if defined(UNIT_TEST)
#elif defined(OS_WIN)
- device_context_(NULL),
+ gl_device_context_(NULL),
gl_context_(NULL),
+ pbuffer_(NULL),
#elif defined(OS_MACOSX)
gl_context_(NULL),
pbuffer_(NULL),
@@ -685,49 +699,62 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
}
bool GLES2DecoderImpl::Initialize() {
- bool success = false;
-
- if (InitPlatformSpecific()) {
- if (MakeCurrent()) {
- if (InitGlew()) {
- CHECK_GL_ERROR();
- success = group_->Initialize();
- if (success) {
- vertex_attrib_infos_.reset(
- new VertexAttribInfo[group_->max_vertex_attribs()]);
- texture_units_.reset(
- new TextureUnit[group_->max_texture_units()]);
- GLuint ids[2];
- glGenTextures(2, ids);
- // Make black textures for replacing non-renderable textures.
- black_2d_texture_id_ = ids[0];
- black_cube_texture_id_ = ids[1];
- static int8 black[] = {0, 0, 0, 0};
- glBindTexture(GL_TEXTURE_2D, black_2d_texture_id_);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, black);
- glBindTexture(GL_TEXTURE_2D, 0);
- glBindTexture(GL_TEXTURE_CUBE_MAP, black_cube_texture_id_);
- static GLenum faces[] = {
- GL_TEXTURE_CUBE_MAP_POSITIVE_X,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
- };
- for (size_t ii = 0; ii < arraysize(faces); ++ii) {
- glTexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, black);
- }
- glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
- CHECK_GL_ERROR();
- }
- }
- }
+ if (!InitPlatformSpecific()) {
+ Destroy();
+ return false;
+ }
+ if (!MakeCurrent()) {
+ Destroy();
+ return false;
+ }
+
+ // This happens in InitializeOneOff in windows. TODO(apatrick): generalize to
+ // other platforms.
+#if !defined(OS_WIN)
+ if (!InitGlew()) {
+ Destroy();
+ return false;
+ }
+#endif
+
+ CHECK_GL_ERROR();
+
+ if (!group_->Initialize()) {
+ Destroy();
+ return false;
+ }
+
+ vertex_attrib_infos_.reset(
+ new VertexAttribInfo[group_->max_vertex_attribs()]);
+ texture_units_.reset(
+ new TextureUnit[group_->max_texture_units()]);
+ GLuint ids[2];
+ glGenTextures(2, ids);
+ // Make black textures for replacing non-renderable textures.
+ black_2d_texture_id_ = ids[0];
+ black_cube_texture_id_ = ids[1];
+ static int8 black[] = {0, 0, 0, 0};
+ glBindTexture(GL_TEXTURE_2D, black_2d_texture_id_);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, black);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, black_cube_texture_id_);
+ static GLenum faces[] = {
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
+ };
+ for (size_t ii = 0; ii < arraysize(faces); ++ii) {
+ glTexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, black);
}
+ glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
+ CHECK_GL_ERROR();
- return success;
+ return true;
}
// TODO(kbr): the use of this anonymous namespace core dumps the
@@ -764,11 +791,9 @@ LRESULT CALLBACK IntermediateWindowProc(HWND window,
return ::DefWindowProc(window, message, w_param, l_param);
}
-// Helper routine that returns the highest quality pixel format supported on
-// the current platform. Returns true upon success.
-bool GetWindowsPixelFormat(HWND window,
- bool anti_aliased,
- int* pixel_format) {
+// Helper routine that does one-off initialization like determining the
+// pixel format and initializing glew.
+bool GLES2DecoderImpl::InitializeOneOff(bool anti_aliased) {
// We must initialize a GL context before we can determine the multi-sampling
// supported on the current hardware, so we create an intermediate window
// and context here.
@@ -815,9 +840,9 @@ bool GetWindowsPixelFormat(HWND window,
}
HDC intermediate_dc = ::GetDC(intermediate_window);
- int format_index = ::ChoosePixelFormat(intermediate_dc,
- &kPixelFormatDescriptor);
- if (format_index == 0) {
+ pixel_format_ = ::ChoosePixelFormat(intermediate_dc,
+ &kPixelFormatDescriptor);
+ if (pixel_format_ == 0) {
DLOG(ERROR) << "Unable to get the pixel format for GL context.";
::ReleaseDC(intermediate_window, intermediate_dc);
::DestroyWindow(intermediate_window);
@@ -825,7 +850,7 @@ bool GetWindowsPixelFormat(HWND window,
module_handle);
return false;
}
- if (!::SetPixelFormat(intermediate_dc, format_index,
+ if (!::SetPixelFormat(intermediate_dc, pixel_format_,
&kPixelFormatDescriptor)) {
DLOG(ERROR) << "Unable to set the pixel format for GL context.";
::ReleaseDC(intermediate_window, intermediate_dc);
@@ -835,18 +860,14 @@ bool GetWindowsPixelFormat(HWND window,
return false;
}
- // Store the pixel format without multisampling.
- *pixel_format = format_index;
+ // Create a temporary GL context to query for multisampled pixel formats.
HGLRC gl_context = ::wglCreateContext(intermediate_dc);
if (::wglMakeCurrent(intermediate_dc, gl_context)) {
// GL context was successfully created and applied to the window's DC.
// Startup GLEW, the GL extensions wrangler.
- GLenum glew_error = ::glewInit();
- if (glew_error == GLEW_OK) {
+ if (InitGlew()) {
DLOG(INFO) << "Initialized GLEW " << ::glewGetString(GLEW_VERSION);
} else {
- DLOG(ERROR) << "Unable to initialise GLEW : "
- << ::glewGetErrorString(glew_error);
::wglMakeCurrent(intermediate_dc, NULL);
::wglDeleteContext(gl_context);
::ReleaseDC(intermediate_window, intermediate_dc);
@@ -887,7 +908,7 @@ bool GetWindowsPixelFormat(HWND window,
1,
&msaa_pixel_format,
&num_formats)) {
- *pixel_format = msaa_pixel_format;
+ pixel_format_ = msaa_pixel_format;
break;
}
}
@@ -968,11 +989,11 @@ bool GLES2DecoderImpl::MakeCurrent() {
#if defined(UNIT_TEST)
return true;
#elif defined(OS_WIN)
- if (::wglGetCurrentDC() == device_context_ &&
+ if (::wglGetCurrentDC() == gl_device_context_ &&
::wglGetCurrentContext() == gl_context_) {
return true;
}
- if (!::wglMakeCurrent(device_context_, gl_context_)) {
+ if (!::wglMakeCurrent(gl_device_context_, gl_context_)) {
DLOG(ERROR) << "Unable to make gl context current.";
return false;
}
@@ -1040,26 +1061,51 @@ void GLES2DecoderImpl::UnregisterObjects(
bool GLES2DecoderImpl::InitPlatformSpecific() {
#if defined(UNIT_TEST)
#elif defined(OS_WIN)
- device_context_ = ::GetDC(hwnd());
+ // Do one-off initialization.
+ static bool success = InitializeOneOff(anti_aliased_);
+ if (!success)
+ return false;
- int pixel_format;
+ if (hwnd()) {
+ // The GL context will render to this window.
+ gl_device_context_ = ::GetDC(hwnd());
- if (!GetWindowsPixelFormat(hwnd(),
- anti_aliased_,
- &pixel_format)) {
- DLOG(ERROR) << "Unable to determine optimal pixel format for GL context.";
+ if (!::SetPixelFormat(gl_device_context_,
+ pixel_format_,
+ &kPixelFormatDescriptor)) {
+ DLOG(ERROR) << "Unable to set the pixel format for GL context.";
+ DestroyPlatformSpecific();
return false;
- }
+ }
+ } else {
+ // Create a device context compatible with the primary display.
+ HDC display_device_context = ::CreateDC(L"DISPLAY", NULL, NULL, NULL);
+
+ // Create a 1 x 1 pbuffer suitable for use with the device.
+ const int kNoAttributes[] = { 0 };
+ pbuffer_ = ::wglCreatePbufferARB(display_device_context,
+ pixel_format_,
+ 1, 1,
+ kNoAttributes);
+ ::DeleteDC(display_device_context);
+ if (!pbuffer_) {
+ DLOG(ERROR) << "Unable to create pbuffer.";
+ DestroyPlatformSpecific();
+ return false;
+ }
- if (!::SetPixelFormat(device_context_, pixel_format,
- &kPixelFormatDescriptor)) {
- DLOG(ERROR) << "Unable to set the pixel format for GL context.";
- return false;
+ gl_device_context_ = ::wglGetPbufferDCARB(pbuffer_);
+ if (!gl_device_context_) {
+ DLOG(ERROR) << "Unable to get pbuffer device context.";
+ DestroyPlatformSpecific();
+ return false;
+ }
}
- gl_context_ = ::wglCreateContext(device_context_);
+ gl_context_ = ::wglCreateContext(gl_device_context_);
if (!gl_context_) {
DLOG(ERROR) << "Failed to create GL context.";
+ DestroyPlatformSpecific();
return false;
}
#elif defined(OS_LINUX)
@@ -1072,20 +1118,20 @@ bool GLES2DecoderImpl::InitPlatformSpecific() {
(CGLPixelFormatAttribute) kCGLPFAPBuffer,
(CGLPixelFormatAttribute) 0
};
- CGLPixelFormatObj pixelFormat;
- GLint numPixelFormats;
+ CGLPixelFormatObj pixel_format;
+ GLint num_pixel_formats;
if (CGLChoosePixelFormat(attribs,
- &pixelFormat,
- &numPixelFormats) != kCGLNoError) {
+ &pixel_format,
+ &num_pixel_formats) != kCGLNoError) {
DLOG(ERROR) << "Error choosing pixel format.";
return false;
}
- if (!pixelFormat) {
+ if (!pixel_format) {
return false;
}
CGLContextObj context;
- CGLError res = CGLCreateContext(pixelFormat, 0, &context);
- CGLDestroyPixelFormat(pixelFormat);
+ CGLError res = CGLCreateContext(pixel_format, 0, &context);
+ CGLDestroyPixelFormat(pixel_format);
if (res != kCGLNoError) {
DLOG(ERROR) << "Error creating context.";
return false;
@@ -1170,6 +1216,29 @@ bool GLES2DecoderImpl::InitGlew() {
return true;
}
+void GLES2DecoderImpl::DestroyPlatformSpecific() {
+#if defined(UNIT_TEST)
+#elif defined(OS_WIN)
+ if (gl_context_) {
+ ::wglDeleteContext(gl_context_);
+ }
+
+ if (gl_device_context_) {
+ if (hwnd())
+ ::ReleaseDC(hwnd(), gl_device_context_);
+ else
+ ::wglReleasePbufferDCARB(pbuffer_, gl_device_context_);
+
+ gl_device_context_ = NULL;
+ }
+
+ if (pbuffer_) {
+ ::wglDestroyPbufferARB(pbuffer_);
+ pbuffer_ = NULL;
+ }
+#endif
+}
+
#if defined(OS_MACOSX)
#if !defined(UNIT_TEST)
static void AddBooleanValue(CFMutableDictionaryRef dictionary,
@@ -1402,6 +1471,8 @@ void GLES2DecoderImpl::Destroy() {
if (pbuffer_)
CGLDestroyPBuffer(pbuffer_);
#endif
+
+ DestroyPlatformSpecific();
}
const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
@@ -1652,7 +1723,7 @@ void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
void GLES2DecoderImpl::DoSwapBuffers() {
#if defined(UNIT_TEST)
#elif defined(OS_WIN)
- ::SwapBuffers(device_context_);
+ ::SwapBuffers(gl_device_context_);
#elif defined(OS_LINUX)
DCHECK(window());
window()->SwapBuffers();
diff --git a/gpu/command_buffer/service/gpu_processor_win.cc b/gpu/command_buffer/service/gpu_processor_win.cc
index bef34d8..bce783b 100644
--- a/gpu/command_buffer/service/gpu_processor_win.cc
+++ b/gpu/command_buffer/service/gpu_processor_win.cc
@@ -11,10 +11,8 @@ using ::base::SharedMemory;
namespace gpu {
bool GPUProcessor::Initialize(gfx::PluginWindowHandle handle) {
- DCHECK(handle);
-
// Cannot reinitialize.
- if (decoder_->hwnd() != NULL)
+ if (parser_.get())
return false;
// Map the ring buffer and create the parser.
@@ -37,8 +35,8 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle handle) {
}
void GPUProcessor::Destroy() {
- // Destroy GAPI if window handle has not already become invalid.
- if (decoder_->hwnd()) {
+ // Destroy decoder if initialized.
+ if (parser_.get()) {
decoder_->Destroy();
decoder_->set_hwnd(NULL);
}