diff options
author | alokp@chromium.org <alokp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-06 20:32:57 +0000 |
---|---|---|
committer | alokp@chromium.org <alokp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-06 20:32:57 +0000 |
commit | 1dcd5e8c3061bcd016dd99a04b939ba23e60497f (patch) | |
tree | 03feb6727eb8ff36802c3d4b104b5fac42ef410a /gpu/demos | |
parent | 2d4d7d554ca674fe43159ff777d6f8f048cec44a (diff) | |
download | chromium_src-1dcd5e8c3061bcd016dd99a04b939ba23e60497f.zip chromium_src-1dcd5e8c3061bcd016dd99a04b939ba23e60497f.tar.gz chromium_src-1dcd5e8c3061bcd016dd99a04b939ba23e60497f.tar.bz2 |
Resubmit 35500: Added an application framework for demos. Ported hellotriangle example in OpenGL ES book to use the application framework.
BUG=26099
TEST=Try running hello_triangle executable, you should see a red triangle.
Review URL: http://codereview.chromium.org/525070
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35647 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/demos')
-rw-r--r-- | gpu/demos/app_framework/application.cc | 161 | ||||
-rw-r--r-- | gpu/demos/app_framework/application.h | 57 | ||||
-rw-r--r-- | gpu/demos/app_framework/gles2_utils.cc | 67 | ||||
-rw-r--r-- | gpu/demos/app_framework/gles2_utils.h | 27 | ||||
-rw-r--r-- | gpu/demos/app_framework/platform.h | 23 | ||||
-rw-r--r-- | gpu/demos/demos.gyp | 46 | ||||
-rw-r--r-- | gpu/demos/hello_triangle/main.cc | 64 |
7 files changed, 445 insertions, 0 deletions
diff --git a/gpu/demos/app_framework/application.cc b/gpu/demos/app_framework/application.cc new file mode 100644 index 0000000..0ae2cb9 --- /dev/null +++ b/gpu/demos/app_framework/application.cc @@ -0,0 +1,161 @@ +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/demos/app_framework/application.h" + +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/gles2_lib.h" +#include "gpu/command_buffer/service/command_buffer_service.h" +#include "gpu/command_buffer/service/gpu_processor.h" + +using gpu::Buffer; +using gpu::CommandBufferService; +using gpu::GPUProcessor; +using gpu::gles2::GLES2CmdHelper; +using gpu::gles2::GLES2Implementation; + +// TODO(alokp): Implement it on mac and linux when gpu process is functional +// on these OS'. +#if defined(OS_WIN) +namespace { +static const int32 kCommandBufferSize = 1024 * 1024; +static const int32 kTransferBufferSize = 512 * 1024; + +static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, + WPARAM w_param, LPARAM l_param) { + LRESULT result = 0; + switch (msg) { + case WM_CLOSE: + ::DestroyWindow(hwnd); + break; + case WM_DESTROY: + ::PostQuitMessage(0); + break; + case WM_PAINT: { + using gpu_demos::Application; + Application* app = reinterpret_cast<Application*>( + GetWindowLongPtr(hwnd, GWL_USERDATA)); + if (app != NULL) app->OnPaint(); + ::ValidateRect(hwnd, NULL); + break; + } + default: + result = ::DefWindowProc(hwnd, msg, w_param, l_param); + break; + } + return result; +} +} // namespace. + +namespace gpu_demos { + +Application::Application() + : width_(512), + height_(512), + window_handle_(NULL) { +} + +Application::~Application() { +} + +void Application::MainLoop() { + MSG msg; + bool done = false; + while (!done) { + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (msg.message == WM_QUIT) done = true; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + // Message queue is empty and application has not quit yet - keep painting. + if (!done) SendMessage(window_handle_, WM_PAINT, 0, 0); + } +} + +void Application::OnPaint() { + Draw(); + gles2::GetGLContext()->SwapBuffers(); +} + +bool Application::InitRenderContext() { + window_handle_ = CreateNativeWindow(); + if (window_handle_ == NULL) { + return false; + } + + scoped_ptr<CommandBufferService> command_buffer(new CommandBufferService); + if (!command_buffer->Initialize(kCommandBufferSize)) { + return false; + } + + scoped_refptr<GPUProcessor> gpu_processor( + new GPUProcessor(command_buffer.get())); + if (!gpu_processor->Initialize(window_handle_)) { + return false; + } + + command_buffer->SetPutOffsetChangeCallback( + NewCallback(gpu_processor.get(), &GPUProcessor::ProcessCommands)); + + GLES2CmdHelper* helper = new GLES2CmdHelper(command_buffer.get()); + if (!helper->Initialize()) { + // TODO(alokp): cleanup. + return false; + } + + int32 transfer_buffer_id = + command_buffer->CreateTransferBuffer(kTransferBufferSize); + Buffer transfer_buffer = + command_buffer->GetTransferBuffer(transfer_buffer_id); + if (transfer_buffer.ptr == NULL) return false; + + gles2::g_gl_impl = new GLES2Implementation(helper, + transfer_buffer.size, + transfer_buffer.ptr, + transfer_buffer_id); + + return command_buffer.release() != NULL; +} + +NativeWindowHandle Application::CreateNativeWindow() { + WNDCLASS wnd_class = {0}; + HINSTANCE instance = GetModuleHandle(NULL); + wnd_class.style = CS_OWNDC; + wnd_class.lpfnWndProc = (WNDPROC)WindowProc; + wnd_class.hInstance = instance; + wnd_class.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wnd_class.lpszClassName = L"opengles2.0"; + if (!RegisterClass(&wnd_class)) return NULL; + + DWORD wnd_style = WS_VISIBLE | WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION; + RECT wnd_rect; + wnd_rect.left = 0; + wnd_rect.top = 0; + wnd_rect.right = width_; + wnd_rect.bottom = height_; + AdjustWindowRect(&wnd_rect, wnd_style, FALSE); + + HWND hwnd = CreateWindow( + wnd_class.lpszClassName, + wnd_class.lpszClassName, + wnd_style, + 0, + 0, + wnd_rect.right - wnd_rect.left, + wnd_rect.bottom - wnd_rect.top, + NULL, + NULL, + instance, + NULL); + if (hwnd == NULL) return NULL; + + ShowWindow(hwnd, SW_SHOWNORMAL); + // Set this to the GWL_USERDATA so that it is available to WindowProc. + SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)this); + + return hwnd; +} + +} // namespace gpu_demos +#endif // defined(OS_WIN) diff --git a/gpu/demos/app_framework/application.h b/gpu/demos/app_framework/application.h new file mode 100644 index 0000000..9851c49 --- /dev/null +++ b/gpu/demos/app_framework/application.h @@ -0,0 +1,57 @@ +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Base class for gles2 applications using command buffer. + +#ifndef GPU_DEMOS_APP_FRAMEWORK_APPLICATION_H_ +#define GPU_DEMOS_APP_FRAMEWORK_APPLICATION_H_ + +#include "base/at_exit.h" +#include "base/message_loop.h" + +#include "gpu/demos/app_framework/platform.h" + +namespace gpu_demos { + +// Acts as a base class for GLES2 applications using command buffer. +// The derived calls needs to call InitRenderContext() to create a render +// surface and initialize a rendering context. Currently it only creates +// an on-screen window. It will be extended to support pepper/nacl plugin +// when pepper 3D api is in place. +class Application { + public: + Application(); + virtual ~Application(); + + // Enters the event processing loop. + void MainLoop(); + void OnPaint(); + + protected: + // Returns the size of rendering surface. + inline int width() const { return width_; } + inline int height() const { return height_; } + + bool InitRenderContext(); + + virtual void Draw() = 0; + + private: + // Creates a native on-screen window. + NativeWindowHandle CreateNativeWindow(); + + int width_; + int height_; + NativeWindowHandle window_handle_; + + // The following two variables are just needed to satisfy + // the assumption that we are running inside a browser. + base::AtExitManager at_exit_manager_; + MessageLoopForUI message_loop_; + + DISALLOW_COPY_AND_ASSIGN(Application); +}; + +} // namespace gpu_demos +#endif // GPU_DEMOS_APP_FRAMEWORK_APPLICATION_H_ diff --git a/gpu/demos/app_framework/gles2_utils.cc b/gpu/demos/app_framework/gles2_utils.cc new file mode 100644 index 0000000..7e7d0e5 --- /dev/null +++ b/gpu/demos/app_framework/gles2_utils.cc @@ -0,0 +1,67 @@ +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/demos/app_framework/gles2_utils.h" + +namespace { +static const int kInfoBufferLength = 1024; +} // namespace + +namespace gpu_demos { +namespace gles2_utils { + +GLuint LoadShader(GLenum type, const char* shader_src) { + GLuint shader = glCreateShader(type); + if (shader == 0) return 0; + + // Load the shader source + glShaderSource(shader, 1, &shader_src, NULL); + // Compile the shader + glCompileShader(shader); + // Check the compile status + GLint value; + glGetShaderiv(shader, GL_COMPILE_STATUS, &value); + if (value == 0) { + char buffer[kInfoBufferLength]; + GLsizei length; + glGetShaderInfoLog(shader, sizeof(buffer), &length, buffer); + std::string log(buffer, length); + DLOG(ERROR) << "Error compiling shader:" << log; + glDeleteShader(shader); + shader = 0; + } + return shader; +} + +GLuint LoadProgram(const char* v_shader_src, const char* f_shader_src) { + GLuint v_shader = LoadShader(GL_VERTEX_SHADER, v_shader_src); + if (v_shader == 0) return 0; + + GLuint f_shader = LoadShader(GL_FRAGMENT_SHADER, f_shader_src); + if (f_shader == 0) return 0; + + // Create the program object + GLuint program_object = glCreateProgram(); + if (program_object == 0) return 0; + + // Link the program and check status. + glAttachShader(program_object, v_shader); + glAttachShader(program_object, f_shader); + glLinkProgram(program_object); + GLint linked = 0; + glGetProgramiv(program_object, GL_LINK_STATUS, &linked); + if (linked == 0) { + char buffer[kInfoBufferLength]; + GLsizei length; + glGetProgramInfoLog(program_object, sizeof(buffer), &length, buffer); + std::string log(buffer, length); + DLOG(ERROR) << "Error linking program:" << log; + glDeleteProgram(program_object); + program_object = 0; + } + return program_object; +} + +} // namespace gles2_utils +} // namespace gpu_demos diff --git a/gpu/demos/app_framework/gles2_utils.h b/gpu/demos/app_framework/gles2_utils.h new file mode 100644 index 0000000..147671f --- /dev/null +++ b/gpu/demos/app_framework/gles2_utils.h @@ -0,0 +1,27 @@ +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Utility OpenGL ES 2.0 functions. + +#ifndef GPU_DEMOS_APP_FRAMEWORK_GLES2_UTILS_H_ +#define GPU_DEMOS_APP_FRAMEWORK_GLES2_UTILS_H_ + +#include <GLES2/gl2.h> + +namespace gpu_demos { +namespace gles2_utils { + +// Uploads and compiles shader source. Returns non-zero shader object id. +// Returns 0 if an error occurs creating or compiling the shader object. +// All errors are logged. +extern GLuint LoadShader(GLenum type, const char* shader_src); + +// Uploads, compiles, and links shader program. Returns non-zero program id. +// Returns 0 if an error occurs creating, compiling, or linking the program +// object. All errors are logged. +extern GLuint LoadProgram(const char* v_shader_src, const char* f_shader_src); + +} // namespace gles2_utils +} // namespace gpu_demos +#endif // GPU_DEMOS_APP_FRAMEWORK_GLES2_UTILS_H_ diff --git a/gpu/demos/app_framework/platform.h b/gpu/demos/app_framework/platform.h new file mode 100644 index 0000000..602979e --- /dev/null +++ b/gpu/demos/app_framework/platform.h @@ -0,0 +1,23 @@ +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Platform-specific types and definitions for native widget handles. + +#ifndef GPU_DEMOS_APP_FRAMEWORK_PLATFORM_H_ +#define GPU_DEMOS_APP_FRAMEWORK_PLATFORM_H_ + +#ifdef _WINDOWS +#include <windows.h> +#endif // _WINDOWS + +#include "build/build_config.h" + +namespace gpu_demos { + +#if defined(OS_WIN) +typedef HWND NativeWindowHandle; +#endif // defined(OS_WIN) + +} // namespace gpu_demos +#endif // GPU_DEMOS_APP_FRAMEWORK_PLATFORM_H_ diff --git a/gpu/demos/demos.gyp b/gpu/demos/demos.gyp new file mode 100644 index 0000000..26cedea --- /dev/null +++ b/gpu/demos/demos.gyp @@ -0,0 +1,46 @@ +# Copyright (c) 2009 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'includes': [ + '../../build/common.gypi', + ], + 'targets': [ + { + 'target_name': 'app_framework', + 'type': 'static_library', + 'dependencies': [ + '../gpu.gyp:command_buffer_client', + '../gpu.gyp:command_buffer_service', + ], + 'sources': [ + 'app_framework/application.cc', + 'app_framework/application.h', + 'app_framework/gles2_utils.cc', + 'app_framework/gles2_utils.h', + 'app_framework/platform.h', + ], + }, + { + 'target_name': 'hello_triangle', + 'type': 'executable', + 'dependencies': [ + 'app_framework', + '../../third_party/gles_book_examples/gles_book_examples.gyp:hello_triangle', + ], + 'sources': [ + 'hello_triangle/main.cc', + ], + }, + ] +} + +# Local Variables: +# tab-width:2 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=2 shiftwidth=2: diff --git a/gpu/demos/hello_triangle/main.cc b/gpu/demos/hello_triangle/main.cc new file mode 100644 index 0000000..124e491 --- /dev/null +++ b/gpu/demos/hello_triangle/main.cc @@ -0,0 +1,64 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is a simple example that draws a single triangle with +// a minimal vertex/fragment shader. The purpose of this +// example is to demonstrate the basic concepts of +// OpenGL ES 2.0 rendering. + +#include "gpu/demos/app_framework/application.h" +#include "third_party/gles_book_examples/Chapter_2/Hello_Triangle/Hello_Triangle.h" + +namespace gpu_demos { +class HelloTriangle : public Application { + public: + HelloTriangle(); + ~HelloTriangle(); + + bool Init(); + + protected: + virtual void Draw(); + + private: + ESContext context_; + HTUserData user_data_; +}; + +HelloTriangle::HelloTriangle() { + esInitContext(&context_); + + memset(&user_data_, 0, sizeof(HTUserData)); + context_.userData = &user_data_; +} + +HelloTriangle::~HelloTriangle() { + htShutDown(&context_); +} + +bool HelloTriangle::Init() { + if (!Application::InitRenderContext()) return false; + + context_.width = width(); + context_.height = height(); + if (!htInit(&context_)) return false; + + return true; +} + +void HelloTriangle::Draw() { + htDraw(&context_); +} +} // namespace gpu_demos + +int main(int argc, char *argv[]) { + gpu_demos::HelloTriangle app; + if (!app.Init()) { + printf("Could not init.\n"); + return EXIT_FAILURE; + } + + app.MainLoop(); + return EXIT_SUCCESS; +} |