summaryrefslogtreecommitdiffstats
path: root/gpu/demos/framework
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/demos/framework')
-rw-r--r--gpu/demos/framework/demo.cc35
-rw-r--r--gpu/demos/framework/demo.h67
-rw-r--r--gpu/demos/framework/demo_factory.h17
-rw-r--r--gpu/demos/framework/main_exe.cc24
-rw-r--r--gpu/demos/framework/main_pepper.cc148
-rw-r--r--gpu/demos/framework/platform.h25
-rw-r--r--gpu/demos/framework/plugin.cc147
-rw-r--r--gpu/demos/framework/plugin.def4
-rw-r--r--gpu/demos/framework/plugin.h51
-rw-r--r--gpu/demos/framework/plugin.rc35
-rw-r--r--gpu/demos/framework/window.cc169
-rw-r--r--gpu/demos/framework/window.h39
12 files changed, 761 insertions, 0 deletions
diff --git a/gpu/demos/framework/demo.cc b/gpu/demos/framework/demo.cc
new file mode 100644
index 0000000..49fa519
--- /dev/null
+++ b/gpu/demos/framework/demo.cc
@@ -0,0 +1,35 @@
+// Copyright (c) 2010 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/framework/demo.h"
+#include "gpu/demos/framework/demo_factory.h"
+
+namespace gpu {
+namespace demos {
+
+Demo::Demo() : width_(0), height_(0) {
+}
+
+Demo::~Demo() {
+}
+
+void Demo::InitWindowSize(int width, int height) {
+ width_ = width;
+ height_ = height;
+}
+
+void Demo::Draw() {
+ float elapsed_sec = 0.0f;
+ const base::Time current_time = base::Time::Now();
+ if (!last_draw_time_.is_null()) {
+ base::TimeDelta time_delta = current_time - last_draw_time_;
+ elapsed_sec = static_cast<float>(time_delta.InSecondsF());
+ }
+ last_draw_time_ = current_time;
+
+ Render(elapsed_sec);
+}
+
+} // namespace demos
+} // namespace gpu
diff --git a/gpu/demos/framework/demo.h b/gpu/demos/framework/demo.h
new file mode 100644
index 0000000..801609b
--- /dev/null
+++ b/gpu/demos/framework/demo.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2010 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 demos.
+
+#ifndef GPU_DEMOS_FRAMEWORK_DEMO_H_
+#define GPU_DEMOS_FRAMEWORK_DEMO_H_
+
+#include "base/time.h"
+
+namespace gpu {
+namespace demos {
+
+// Base class for GLES2 demos. The same demo class is supposed to be run as
+// standalone apps (exe), pepper plugin (dll), and nacl module (nexe). This is
+// accomplished by creating framework for each platfom and hosting the demo
+// class object.
+class Demo {
+ public:
+ Demo();
+ virtual ~Demo();
+
+ // Returns the title of demo. This title is used to name the window or
+ // html page where demo is running.
+ virtual const wchar_t* Title() const = 0;
+
+ // Initializes the size of the window on which this demo object will render.
+ void InitWindowSize(int width, int height);
+
+ // This function is called by the framework to initialize the OpenGL state
+ // required by this demo. When this function is called, it is assumed that
+ // a rendering context has already been created and made current.
+ virtual bool InitGL() = 0;
+
+ // This function is called by the framework to perform OpenGL rendering.
+ // When this function is called, it is assumed that the rendering context
+ // has been made current.
+ void Draw();
+
+ protected:
+ // Returns the width of window.
+ int width() const { return width_; }
+ // Returns the height of window.
+ int height() const { return height_; }
+
+ // The framework calls this function for the derived classes to do custom
+ // rendering. There is no default implementation. It must be defined by the
+ // derived classes. The elapsed_sec param represents the time elapsed
+ // (in seconds) after Render was called the last time. It can be used to
+ // make the application frame-rate independent. It is 0.0f for the
+ // first render call.
+ virtual void Render(float elapsed_sec) = 0;
+
+ private:
+ int width_; // Window width.
+ int height_; // Window height.
+
+ // Time at which draw was called last.
+ base::Time last_draw_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(Demo);
+};
+
+} // namespace demos
+} // namespace gpu
+#endif // GPU_DEMOS_FRAMEWORK_DEMO_H_
diff --git a/gpu/demos/framework/demo_factory.h b/gpu/demos/framework/demo_factory.h
new file mode 100644
index 0000000..1cecc9f
--- /dev/null
+++ b/gpu/demos/framework/demo_factory.h
@@ -0,0 +1,17 @@
+// Copyright (c) 2010 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.
+
+#ifndef GPU_DEMOS_FRAMEWORK_DEMO_FACTORY_H_
+#define GPU_DEMOS_FRAMEWORK_DEMO_FACTORY_H_
+
+namespace gpu {
+namespace demos {
+
+class Demo;
+
+extern Demo* CreateDemo();
+
+} // namespace demos
+} // namespace gpu
+#endif // GPU_DEMOS_FRAMEWORK_DEMO_FACTORY_H_
diff --git a/gpu/demos/framework/main_exe.cc b/gpu/demos/framework/main_exe.cc
new file mode 100644
index 0000000..fa4e726
--- /dev/null
+++ b/gpu/demos/framework/main_exe.cc
@@ -0,0 +1,24 @@
+// Copyright (c) 2010 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 "base/at_exit.h"
+#include "base/logging.h"
+#include "gpu/demos/framework/window.h"
+
+namespace {
+static const int kWindowWidth = 512;
+static const int kWindowHeight = 512;
+} // namespace.
+
+int main(int argc, char *argv[]) {
+ // AtExitManager is used by singleton classes to delete themselves when
+ // the program terminates.
+ base::AtExitManager at_exit_manager_;
+
+ gpu::demos::Window window;
+ CHECK(window.Init(kWindowWidth, kWindowHeight));
+
+ window.MainLoop();
+ return EXIT_SUCCESS;
+}
diff --git a/gpu/demos/framework/main_pepper.cc b/gpu/demos/framework/main_pepper.cc
new file mode 100644
index 0000000..d97cbd0
--- /dev/null
+++ b/gpu/demos/framework/main_pepper.cc
@@ -0,0 +1,148 @@
+// Copyright (c) 2010 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 "base/at_exit.h"
+#include "base/logging.h"
+#include "gpu/demos/framework/plugin.h"
+#include "webkit/glue/plugins/nphostapi.h"
+
+namespace {
+// AtExitManager is used by singleton classes to delete themselves when
+// the program terminates. There should be only one instance of this class
+// per thread;
+base::AtExitManager* g_at_exit_manager_;
+} // namespace
+
+namespace gpu {
+namespace demos {
+// NPP entry points.
+NPError NPP_New(NPMIMEType pluginType,
+ NPP instance,
+ uint16 mode,
+ int16 argc, char* argn[], char* argv[],
+ NPSavedData* saved) {
+ if (g_browser->version < NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL) {
+ return NPERR_INCOMPATIBLE_VERSION_ERROR;
+ }
+
+ Plugin* plugin = static_cast<Plugin*>(
+ g_browser->createobject(instance, Plugin::GetPluginClass()));
+ instance->pdata = plugin;
+ plugin->New(pluginType, argc, argn, argv);
+
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_Destroy(NPP instance, NPSavedData** save) {
+ Plugin* plugin = static_cast<Plugin*>(instance->pdata);
+ if (plugin) g_browser->releaseobject(plugin);
+
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_SetWindow(NPP instance, NPWindow* window) {
+ Plugin* plugin = static_cast<Plugin*>(instance->pdata);
+ if (plugin) plugin->SetWindow(*window);
+
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_NewStream(NPP instance,
+ NPMIMEType type,
+ NPStream* stream,
+ NPBool seekable,
+ uint16* stype) {
+ *stype = NP_ASFILEONLY;
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) {
+ return NPERR_NO_ERROR;
+}
+
+void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) {
+}
+
+int32 NPP_Write(NPP instance,
+ NPStream* stream,
+ int32 offset,
+ int32 len,
+ void* buffer) {
+ return 0;
+}
+
+int32 NPP_WriteReady(NPP instance, NPStream* stream) {
+ return 0;
+}
+
+void NPP_Print(NPP instance, NPPrint* platformPrint) {
+}
+
+int16 NPP_HandleEvent(NPP instance, void* event) {
+ return 0;
+}
+
+void NPP_URLNotify(NPP instance, const char* url, NPReason reason,
+ void* notify_data) {
+}
+
+NPError NPP_GetValue(NPP instance, NPPVariable variable, void* value) {
+ NPError err = NPERR_NO_ERROR;
+
+ switch (variable) {
+ case NPPVpluginScriptableNPObject: {
+ void** v = reinterpret_cast<void**>(value);
+ Plugin* plugin = static_cast<Plugin*>(instance->pdata);
+ // Return value is expected to be retained
+ g_browser->retainobject(plugin);
+ *v = plugin;
+ break;
+ }
+ default:
+ LOG(INFO) << "Unhandled variable to NPP_GetValue\n";
+ err = NPERR_GENERIC_ERROR;
+ break;
+ }
+
+ return err;
+}
+
+NPError NPP_SetValue(NPP instance, NPNVariable variable, void* value) {
+ return NPERR_GENERIC_ERROR;
+}
+} // namespace demos
+} // namespace gpu
+
+// NP entry points
+extern "C" {
+NPError API_CALL NP_GetEntryPoints(NPPluginFuncs* plugin_funcs) {
+ plugin_funcs->version = NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL;
+ plugin_funcs->size = sizeof(plugin_funcs);
+ plugin_funcs->newp = gpu::demos::NPP_New;
+ plugin_funcs->destroy = gpu::demos::NPP_Destroy;
+ plugin_funcs->setwindow = gpu::demos::NPP_SetWindow;
+ plugin_funcs->newstream = gpu::demos::NPP_NewStream;
+ plugin_funcs->destroystream = gpu::demos::NPP_DestroyStream;
+ plugin_funcs->asfile = gpu::demos::NPP_StreamAsFile;
+ plugin_funcs->writeready = gpu::demos::NPP_WriteReady;
+ plugin_funcs->write = gpu::demos::NPP_Write;
+ plugin_funcs->print = gpu::demos::NPP_Print;
+ plugin_funcs->event = gpu::demos::NPP_HandleEvent;
+ plugin_funcs->urlnotify = gpu::demos::NPP_URLNotify;
+ plugin_funcs->getvalue = gpu::demos::NPP_GetValue;
+ plugin_funcs->setvalue = gpu::demos::NPP_SetValue;
+
+ return NPERR_NO_ERROR;
+}
+
+NPError API_CALL NP_Initialize(NPNetscapeFuncs* browser_funcs) {
+ g_at_exit_manager_ = new base::AtExitManager();
+ gpu::demos::g_browser = browser_funcs;
+ return NPERR_NO_ERROR;
+}
+
+void API_CALL NP_Shutdown() {
+ delete g_at_exit_manager_;
+}
+} // extern "C"
diff --git a/gpu/demos/framework/platform.h b/gpu/demos/framework/platform.h
new file mode 100644
index 0000000..cd6c003
--- /dev/null
+++ b/gpu/demos/framework/platform.h
@@ -0,0 +1,25 @@
+// 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_FRAMEWORK_PLATFORM_H_
+#define GPU_DEMOS_FRAMEWORK_PLATFORM_H_
+
+#ifdef _WINDOWS
+#include <windows.h>
+#endif // _WINDOWS
+
+#include "build/build_config.h"
+
+namespace gpu {
+namespace demos {
+
+#if defined(OS_WIN)
+typedef HWND NativeWindowHandle;
+#endif // defined(OS_WIN)
+
+} // namespace demos
+} // namespace gpu
+#endif // GPU_DEMOS_FRAMEWORK_PLATFORM_H_
diff --git a/gpu/demos/framework/plugin.cc b/gpu/demos/framework/plugin.cc
new file mode 100644
index 0000000..b5278b1
--- /dev/null
+++ b/gpu/demos/framework/plugin.cc
@@ -0,0 +1,147 @@
+// Copyright (c) 2010 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/framework/plugin.h"
+
+#include "base/logging.h"
+#include "gpu/demos/framework/demo_factory.h"
+
+namespace {
+const int32 kCommandBufferSize = 1024 * 1024;
+NPExtensions* g_extensions = NULL;
+
+// Plugin class functions.
+using gpu::demos::Plugin;
+NPObject* PluginAllocate(NPP npp, NPClass* the_class) {
+ Plugin* plugin = new Plugin(npp);
+ return plugin;
+}
+
+void PluginDeallocate(NPObject* header) {
+ Plugin* plugin = static_cast<Plugin*>(header);
+ delete plugin;
+}
+
+void PluginInvalidate(NPObject* obj) {
+}
+
+bool PluginHasMethod(NPObject* obj, NPIdentifier name) {
+ return false;
+}
+
+bool PluginInvoke(NPObject* header,
+ NPIdentifier name,
+ const NPVariant* args, uint32 arg_count,
+ NPVariant* result) {
+ return false;
+}
+
+bool PluginInvokeDefault(NPObject* obj,
+ const NPVariant* args, uint32 arg_count,
+ NPVariant* result) {
+ VOID_TO_NPVARIANT(*result);
+ return true;
+}
+
+bool PluginHasProperty(NPObject* obj, NPIdentifier name) {
+ return false;
+}
+
+bool PluginGetProperty(NPObject* obj,
+ NPIdentifier name,
+ NPVariant* result) {
+ return false;
+}
+
+bool PluginSetProperty(NPObject* obj,
+ NPIdentifier name,
+ const NPVariant* variant) {
+ return false;
+}
+
+NPClass plugin_class = {
+ NP_CLASS_STRUCT_VERSION,
+ PluginAllocate,
+ PluginDeallocate,
+ PluginInvalidate,
+ PluginHasMethod,
+ PluginInvoke,
+ PluginInvokeDefault,
+ PluginHasProperty,
+ PluginGetProperty,
+ PluginSetProperty,
+};
+
+void PaintCallback(void* data) {
+ reinterpret_cast<gpu::demos::Plugin*>(data)->Paint();
+}
+}
+
+namespace gpu {
+namespace demos {
+
+NPNetscapeFuncs* g_browser;
+
+Plugin::Plugin(NPP npp)
+ : npp_(npp),
+ device3d_(NULL),
+ pgl_context_(NULL),
+ demo_(CreateDemo()) {
+ memset(&context3d_, 0, sizeof(context3d_));
+}
+
+Plugin::~Plugin() {
+ pglMakeCurrent(NULL);
+ pglDestroyContext(pgl_context_);
+}
+
+NPClass* Plugin::GetPluginClass() {
+ return &plugin_class;
+}
+
+void Plugin::New(NPMIMEType pluginType,
+ int16 argc, char* argn[], char* argv[]) {
+ if (!g_extensions) {
+ g_browser->getvalue(npp_, NPNVPepperExtensions, &g_extensions);
+ CHECK(g_extensions);
+ }
+
+ device3d_ = g_extensions->acquireDevice(npp_, NPPepper3DDevice);
+ CHECK(device3d_);
+}
+
+void Plugin::SetWindow(const NPWindow& window) {
+ if (!pgl_context_) {
+ // Initialize a 3D context.
+ NPDeviceContext3DConfig config;
+ config.commandBufferEntries = kCommandBufferSize;
+ device3d_->initializeContext(npp_, &config, &context3d_);
+
+ // Create a PGL context.
+ pgl_context_ = pglCreateContext(npp_, device3d_, &context3d_);
+
+ // Initialize demo.
+ pglMakeCurrent(pgl_context_);
+ demo_->InitWindowSize(window.width, window.height);
+ CHECK(demo_->InitGL());
+ pglMakeCurrent(NULL);
+ }
+
+ // Schedule the first call to Draw.
+ g_browser->pluginthreadasynccall(npp_, PaintCallback, this);
+}
+
+void Plugin::Paint() {
+ // Render some stuff.
+ pglMakeCurrent(pgl_context_);
+ demo_->Draw();
+ pglSwapBuffers();
+ pglMakeCurrent(NULL);
+
+ // Schedule another call to Paint.
+ g_browser->pluginthreadasynccall(npp_, PaintCallback, this);
+}
+
+} // namespace demos
+} // namespace gpu
diff --git a/gpu/demos/framework/plugin.def b/gpu/demos/framework/plugin.def
new file mode 100644
index 0000000..ddc24ce
--- /dev/null
+++ b/gpu/demos/framework/plugin.def
@@ -0,0 +1,4 @@
+EXPORTS
+ NP_GetEntryPoints @1
+ NP_Initialize @2
+ NP_Shutdown @3
diff --git a/gpu/demos/framework/plugin.h b/gpu/demos/framework/plugin.h
new file mode 100644
index 0000000..7832d3b
--- /dev/null
+++ b/gpu/demos/framework/plugin.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2010 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.
+
+#ifndef GPU_DEMOS_FRAMEWORK_PLUGIN_H_
+#define GPU_DEMOS_FRAMEWORK_PLUGIN_H_
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "gpu/demos/framework/demo.h"
+#include "gpu/pgl/pgl.h"
+#include "webkit/glue/plugins/nphostapi.h"
+
+namespace gpu {
+namespace demos {
+
+// Acts as a framework for pepper3d demos. It is in fact a pepper plugin with
+// a pepper3d device. It delegates all rendering tasks to demo object.
+class Plugin : public NPObject {
+ public:
+ explicit Plugin(NPP npp);
+ ~Plugin();
+
+ static NPClass* GetPluginClass();
+
+ NPP npp() const { return npp_; }
+ void New(NPMIMEType pluginType, int16 argc, char* argn[], char* argv[]);
+ void SetWindow(const NPWindow& window);
+
+ // Called by the browser to paint the window.
+ void Paint();
+
+ private:
+ // This class object needs to be safely casted to NPObject* and cross
+ // c-c++ module boundaries. To accomplish that this class should not have
+ // any virtual member function.
+ NPP npp_;
+
+ NPDevice* device3d_;
+ NPDeviceContext3D context3d_;
+ PGLContext pgl_context_;
+ scoped_ptr<Demo> demo_;
+
+ DISALLOW_COPY_AND_ASSIGN(Plugin);
+};
+
+extern NPNetscapeFuncs* g_browser;
+
+} // namespace demos
+} // namespace gpu
+#endif // GPU_DEMOS_FRAMEWORK_PLUGIN_H_
diff --git a/gpu/demos/framework/plugin.rc b/gpu/demos/framework/plugin.rc
new file mode 100644
index 0000000..ee6b4fa
--- /dev/null
+++ b/gpu/demos/framework/plugin.rc
@@ -0,0 +1,35 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+1 VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x7L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "Pepper GPU Demo"
+ VALUE "FileVersion", "1, 0, 0, 1"
+ VALUE "LegalCopyright", "Copyright (C) 2010"
+ VALUE "ProductName", "Pepper GPU Demo"
+ VALUE "ProductVersion", "1, 0, 0, 1"
+ VALUE "MIMEType", "pepper-application/x-gpu-demo"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/gpu/demos/framework/window.cc b/gpu/demos/framework/window.cc
new file mode 100644
index 0000000..6833feb
--- /dev/null
+++ b/gpu/demos/framework/window.cc
@@ -0,0 +1,169 @@
+// Copyright (c) 2010 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/framework/window.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"
+#include "gpu/demos/framework/demo_factory.h"
+
+using gpu::Buffer;
+using gpu::CommandBufferService;
+using gpu::GPUProcessor;
+using gpu::gles2::GLES2CmdHelper;
+using gpu::gles2::GLES2Implementation;
+
+// TODO(alokp): Make this class cross-platform. Investigate using SDL.
+namespace {
+const int32 kCommandBufferSize = 1024 * 1024;
+const int32 kTransferBufferSize = 512 * 1024;
+
+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_ERASEBKGND:
+ break;
+ case WM_PAINT: {
+ gpu::demos::Window* window = reinterpret_cast<gpu::demos::Window*>(
+ GetWindowLongPtr(hwnd, GWL_USERDATA));
+ if (window != NULL) window->OnPaint();
+ ::ValidateRect(hwnd, NULL);
+ break;
+ }
+ default:
+ result = ::DefWindowProc(hwnd, msg, w_param, l_param);
+ break;
+ }
+ return result;
+}
+
+HWND CreateNativeWindow(const wchar_t* title, int width, int height,
+ LONG_PTR user_data) {
+ WNDCLASS wnd_class = {0};
+ HINSTANCE instance = GetModuleHandle(NULL);
+ wnd_class.style = CS_OWNDC;
+ wnd_class.lpfnWndProc = WindowProc;
+ wnd_class.hInstance = instance;
+ wnd_class.hbrBackground =
+ reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH));
+ wnd_class.lpszClassName = L"gpu_demo";
+ 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,
+ title,
+ 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, user_data);
+
+ return hwnd;
+}
+
+bool InitRenderContext(HWND hwnd) {
+ CHECK(hwnd);
+
+ 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(hwnd)) {
+ 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::SetGLContext(new GLES2Implementation(helper,
+ transfer_buffer.size,
+ transfer_buffer.ptr,
+ transfer_buffer_id));
+ return command_buffer.release() != NULL;
+}
+} // namespace.
+
+namespace gpu {
+namespace demos {
+
+Window::Window()
+ : window_handle_(NULL),
+ demo_(CreateDemo()) {
+}
+
+Window::~Window() {
+}
+
+bool Window::Init(int width, int height) {
+ window_handle_ = CreateNativeWindow(demo_->Title(), width, height,
+ reinterpret_cast<LONG_PTR>(this));
+ if (window_handle_ == NULL) return false;
+ if (!InitRenderContext(window_handle_)) return false;
+
+ demo_->InitWindowSize(width, height);
+ return demo_->InitGL();
+}
+
+void Window::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) ::UpdateWindow(window_handle_);
+ }
+}
+
+void Window::OnPaint() {
+ demo_->Draw();
+ ::gles2::GetGLContext()->SwapBuffers();
+}
+
+} // namespace demos
+} // namespace gpu
diff --git a/gpu/demos/framework/window.h b/gpu/demos/framework/window.h
new file mode 100644
index 0000000..dade945
--- /dev/null
+++ b/gpu/demos/framework/window.h
@@ -0,0 +1,39 @@
+// 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.
+
+#ifndef GPU_DEMOS_FRAMEWORK_WINDOW_H_
+#define GPU_DEMOS_FRAMEWORK_WINDOW_H_
+
+#include "base/scoped_ptr.h"
+#include "gpu/demos/framework/demo.h"
+#include "gpu/demos/framework/platform.h"
+
+namespace gpu {
+namespace demos {
+
+// Acts as a framework for standalone demos. It creates a window and delegates
+// all events to demo to perform rendering and other tasks.
+class Window {
+ public:
+ Window();
+ virtual ~Window();
+
+ // Initializes and creates a window with given dimensions.
+ bool Init(int width, int height);
+
+ // Enters the event processing loop.
+ void MainLoop();
+
+ void OnPaint();
+
+ private:
+ NativeWindowHandle window_handle_;
+ scoped_ptr<Demo> demo_;
+
+ DISALLOW_COPY_AND_ASSIGN(Window);
+};
+
+} // namespace demos
+} // namespace gpu
+#endif // GPU_DEMOS_FRAMEWORK_WINDOW_H_