diff options
author | alokp@chromium.org <alokp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-26 02:53:54 +0000 |
---|---|---|
committer | alokp@chromium.org <alokp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-26 02:53:54 +0000 |
commit | 326975bc6d456cf9fd4a6d944ce1f9f5f834e7e4 (patch) | |
tree | 544760f0e2efb3a6e81ab024ea51adc4b7c0dddd /gpu | |
parent | a651b74d09d8f96d6dbb488dde3c494d97544886 (diff) | |
download | chromium_src-326975bc6d456cf9fd4a6d944ce1f9f5f834e7e4.zip chromium_src-326975bc6d456cf9fd4a6d944ce1f9f5f834e7e4.tar.gz chromium_src-326975bc6d456cf9fd4a6d944ce1f9f5f834e7e4.tar.bz2 |
Added infrastructure to run gpu demos under Pepper3D. Created a Demo class that can be run as both standalone apps (exe) or pepper plugins (dll). Created entry points and framework classes for both platforms - exe and pepper. A demo application has three layers:
1. Entry point
- standalone (main_exe.cc): Contains the main function for console applications. Instantiates and runs a window.
- pepper (main_pepper.cc): Contains NPAPI entry points. Instantiates pepper plugin object.
2. Framework that hosts demo
- standalone: Window
- pepper: Plugin
3. Demo - One demo class for all platforms. This does all the rendering and event handling.
BUG=26099
Review URL: http://codereview.chromium.org/554053
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37082 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r-- | gpu/demos/app_framework/application.h | 68 | ||||
-rw-r--r-- | gpu/demos/demos.gyp | 112 | ||||
-rw-r--r-- | gpu/demos/framework/demo.cc | 35 | ||||
-rw-r--r-- | gpu/demos/framework/demo.h | 67 | ||||
-rw-r--r-- | gpu/demos/framework/demo_factory.h | 17 | ||||
-rw-r--r-- | gpu/demos/framework/main_exe.cc | 24 | ||||
-rw-r--r-- | gpu/demos/framework/main_pepper.cc | 148 | ||||
-rw-r--r-- | gpu/demos/framework/platform.h (renamed from gpu/demos/app_framework/platform.h) | 12 | ||||
-rw-r--r-- | gpu/demos/framework/plugin.cc | 147 | ||||
-rw-r--r-- | gpu/demos/framework/plugin.def | 4 | ||||
-rw-r--r-- | gpu/demos/framework/plugin.h | 51 | ||||
-rw-r--r-- | gpu/demos/framework/plugin.rc | 35 | ||||
-rw-r--r-- | gpu/demos/framework/window.cc (renamed from gpu/demos/app_framework/application.cc) | 182 | ||||
-rw-r--r-- | gpu/demos/framework/window.h | 39 | ||||
-rw-r--r-- | gpu/demos/gles2_book/example.h | 52 | ||||
-rw-r--r-- | gpu/demos/gles2_book/hello_triangle.cc (renamed from gpu/demos/hello_triangle/main.cc) | 32 | ||||
-rw-r--r-- | gpu/demos/pepper_gpu_demo.html | 12 |
17 files changed, 781 insertions, 256 deletions
diff --git a/gpu/demos/app_framework/application.h b/gpu/demos/app_framework/application.h deleted file mode 100644 index d9d48e9..0000000 --- a/gpu/demos/app_framework/application.h +++ /dev/null @@ -1,68 +0,0 @@ -// 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 "base/time.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 width of rendering surface. - inline int width() const { return width_; } - // Returns the height of rendering surface. - inline int height() const { return height_; } - - bool InitRenderContext(); - - // 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 Draw was called the last time. It can be used to - // make the application frame-rate independent. It is 0.0f for the - // first draw call. - virtual void Draw(float elapsed_sec) = 0; - - private: - // Creates a native on-screen window. - NativeWindowHandle CreateNativeWindow(); - - int width_; - int height_; - NativeWindowHandle window_handle_; - - // Time at which draw was called last. - base::Time last_draw_time_; - - // 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/demos.gyp b/gpu/demos/demos.gyp index 99aa697..307e50b 100644 --- a/gpu/demos/demos.gyp +++ b/gpu/demos/demos.gyp @@ -11,93 +11,87 @@ ], 'targets': [ { - 'target_name': 'app_framework', + 'target_name': 'gpu_demo_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/platform.h', - ], - }, - { - 'target_name': 'hello_triangle', - 'type': 'executable', - 'dependencies': [ - 'app_framework', - '../../third_party/gles2_book/gles2_book.gyp:hello_triangle', - ], - 'sources': [ - 'hello_triangle/main.cc', - ], - }, - { - 'target_name': 'mip_map_2d', - 'type': 'executable', - 'dependencies': [ - 'app_framework', - '../../third_party/gles2_book/gles2_book.gyp:mip_map_2d', + '../../base/base.gyp:base', ], 'sources': [ - 'mip_map_2d/main.cc', + 'framework/demo.cc', + 'framework/demo.h', + 'framework/demo_factory.h', ], }, { - 'target_name': 'simple_texture_2d', - 'type': 'executable', - 'dependencies': [ - 'app_framework', - '../../third_party/gles2_book/gles2_book.gyp:simple_texture_2d', - ], - 'sources': [ - 'simple_texture_2d/main.cc', - ], - }, - { - 'target_name': 'simple_texture_cubemap', - 'type': 'executable', + 'target_name': 'gpu_demo_framework_exe', + 'type': 'static_library', 'dependencies': [ - 'app_framework', - '../../third_party/gles2_book/gles2_book.gyp:simple_texture_cubemap', + 'gpu_demo_framework', + '../gpu.gyp:command_buffer_client', + '../gpu.gyp:command_buffer_service', ], + 'all_dependent_settings': { + 'sources': [ + 'framework/main_exe.cc', + ], + }, 'sources': [ - 'simple_texture_cubemap/main.cc', + 'framework/platform.h', + 'framework/window.cc', + 'framework/window.h', ], }, { - 'target_name': 'simple_vertex_shader', - 'type': 'executable', + 'target_name': 'gpu_demo_framework_pepper', + 'type': 'static_library', 'dependencies': [ - 'app_framework', - '../../third_party/gles2_book/gles2_book.gyp:simple_vertex_shader', - ], + 'gpu_demo_framework', + '../gpu.gyp:pgl', + ], + 'all_dependent_settings': { + 'sources': [ + 'framework/main_pepper.cc', + 'framework/plugin.def', + 'framework/plugin.rc', + ], + 'run_as': { + 'action': [ + '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)chrome<(EXECUTABLE_SUFFIX)', + '--no-sandbox', + '--internal-pepper', + '--enable-gpu-plugin', + '--load-plugin=$(TargetPath)', + 'file://$(ProjectDir)pepper_gpu_demo.html', + ], + }, + }, 'sources': [ - 'simple_vertex_shader/main.cc', + 'framework/plugin.cc', + 'framework/plugin.h', ], }, { - 'target_name': 'stencil_test', + 'target_name': 'hello_triangle_exe', 'type': 'executable', 'dependencies': [ - 'app_framework', - '../../third_party/gles2_book/gles2_book.gyp:stencil_test', + 'gpu_demo_framework_exe', + '../../third_party/gles2_book/gles2_book.gyp:hello_triangle', ], 'sources': [ - 'stencil_test/main.cc', + 'gles2_book/example.h', + 'gles2_book/hello_triangle.cc', ], }, { - 'target_name': 'texture_wrap', - 'type': 'executable', + 'target_name': 'hello_triangle_pepper', + 'type': 'shared_library', 'dependencies': [ - 'app_framework', - '../../third_party/gles2_book/gles2_book.gyp:texture_wrap', + 'gpu_demo_framework_pepper', + '../../third_party/gles2_book/gles2_book.gyp:hello_triangle', ], 'sources': [ - 'texture_wrap/main.cc', + 'gles2_book/example.h', + 'gles2_book/hello_triangle.cc', ], }, ] 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/app_framework/platform.h b/gpu/demos/framework/platform.h index 602979e..cd6c003 100644 --- a/gpu/demos/app_framework/platform.h +++ b/gpu/demos/framework/platform.h @@ -4,8 +4,8 @@ // Platform-specific types and definitions for native widget handles. -#ifndef GPU_DEMOS_APP_FRAMEWORK_PLATFORM_H_ -#define GPU_DEMOS_APP_FRAMEWORK_PLATFORM_H_ +#ifndef GPU_DEMOS_FRAMEWORK_PLATFORM_H_ +#define GPU_DEMOS_FRAMEWORK_PLATFORM_H_ #ifdef _WINDOWS #include <windows.h> @@ -13,11 +13,13 @@ #include "build/build_config.h" -namespace gpu_demos { +namespace gpu { +namespace demos { #if defined(OS_WIN) typedef HWND NativeWindowHandle; #endif // defined(OS_WIN) -} // namespace gpu_demos -#endif // GPU_DEMOS_APP_FRAMEWORK_PLATFORM_H_ +} // 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/app_framework/application.cc b/gpu/demos/framework/window.cc index b82e691a..6833feb 100644 --- a/gpu/demos/app_framework/application.cc +++ b/gpu/demos/framework/window.cc @@ -1,13 +1,14 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// 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/app_framework/application.h" +#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; @@ -15,15 +16,13 @@ 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) +// TODO(alokp): Make this class cross-platform. Investigate using SDL. namespace { -static const int32 kCommandBufferSize = 1024 * 1024; -static const int32 kTransferBufferSize = 512 * 1024; +const int32 kCommandBufferSize = 1024 * 1024; +const int32 kTransferBufferSize = 512 * 1024; -static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, - WPARAM w_param, LPARAM l_param) { +LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, + WPARAM w_param, LPARAM l_param) { LRESULT result = 0; switch (msg) { case WM_CLOSE: @@ -32,11 +31,12 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, case WM_DESTROY: ::PostQuitMessage(0); break; + case WM_ERASEBKGND: + break; case WM_PAINT: { - using gpu_demos::Application; - Application* app = reinterpret_cast<Application*>( + gpu::demos::Window* window = reinterpret_cast<gpu::demos::Window*>( GetWindowLongPtr(hwnd, GWL_USERDATA)); - if (app != NULL) app->OnPaint(); + if (window != NULL) window->OnPaint(); ::ValidateRect(hwnd, NULL); break; } @@ -46,51 +46,50 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, } return result; } -} // namespace. - -namespace gpu_demos { -Application::Application() - : width_(512), - height_(512), - window_handle_(NULL) { -} +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; -Application::~Application() { -} + 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); -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); - } -} + 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; -void Application::OnPaint() { - 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; + ShowWindow(hwnd, SW_SHOWNORMAL); + // Set this to the GWL_USERDATA so that it is available to WindowProc. + SetWindowLongPtr(hwnd, GWL_USERDATA, user_data); - Draw(elapsed_sec); - gles2::GetGLContext()->SwapBuffers(); + return hwnd; } -bool Application::InitRenderContext() { - window_handle_ = CreateNativeWindow(); - if (window_handle_ == NULL) { - return false; - } +bool InitRenderContext(HWND hwnd) { + CHECK(hwnd); scoped_ptr<CommandBufferService> command_buffer(new CommandBufferService); if (!command_buffer->Initialize(kCommandBufferSize)) { @@ -99,7 +98,7 @@ bool Application::InitRenderContext() { scoped_refptr<GPUProcessor> gpu_processor( new GPUProcessor(command_buffer.get())); - if (!gpu_processor->Initialize(window_handle_)) { + if (!gpu_processor->Initialize(hwnd)) { return false; } @@ -118,52 +117,53 @@ bool Application::InitRenderContext() { 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); - + gles2::SetGLContext(new GLES2Implementation(helper, + transfer_buffer.size, + transfer_buffer.ptr, + transfer_buffer_id)); return command_buffer.release() != NULL; } +} // namespace. -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; +namespace gpu { +namespace demos { - 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); +Window::Window() + : window_handle_(NULL), + demo_(CreateDemo()) { +} - 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; +Window::~Window() { +} - ShowWindow(hwnd, SW_SHOWNORMAL); - // Set this to the GWL_USERDATA so that it is available to WindowProc. - SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)this); +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; - return hwnd; + 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 gpu_demos -#endif // defined(OS_WIN) +} // 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_ diff --git a/gpu/demos/gles2_book/example.h b/gpu/demos/gles2_book/example.h index 839dfe3..5facbdd 100644 --- a/gpu/demos/gles2_book/example.h +++ b/gpu/demos/gles2_book/example.h @@ -7,7 +7,7 @@ #ifndef GPU_DEMOS_GLES2_BOOK_EXAMPLE_H_ #define GPU_DEMOS_GLES2_BOOK_EXAMPLE_H_ -#include "gpu/demos/app_framework/application.h" +#include "gpu/demos/framework/demo.h" #include "third_party/gles2_book/Common/Include/esUtil.h" namespace gpu { @@ -28,47 +28,61 @@ typedef void ShutDownFunc(ESContext* context); // 4. ShutDownFunc is called when program terminates // This class encapsulates this pattern to make it easier to write classes // for each example. -template <typename UserData, - InitFunc init_func, - UpdateFunc update_func, - DrawFunc draw_func, - ShutDownFunc shut_down_func> -class Example : public gpu_demos::Application { +template <typename UserData> +class Example : public gpu::demos::Demo { public: - Example() { + Example() + : init_func_(NULL), + update_func_(NULL), + draw_func_(NULL), + shut_down_func_(NULL) { esInitContext(&context_); memset(&user_data_, 0, sizeof(UserData)); context_.userData = &user_data_; } virtual ~Example() { - shut_down_func(&context_); + shut_down_func_(&context_); } - bool Init() { - if (!InitRenderContext()) return false; + virtual bool InitGL() { + // Note that update_func is optional. + CHECK(init_func_ && draw_func_ && shut_down_func_); context_.width = width(); context_.height = height(); - if (!init_func(&context_)) return false; + if (!init_func_(&context_)) return false; return true; } protected: - virtual void Draw(float elapsed_sec) { - update_func(&context_, elapsed_sec); - draw_func(&context_); + void RegisterCallbacks(InitFunc* init_func, + UpdateFunc* update_func, + DrawFunc* draw_func, + ShutDownFunc* shut_down_func) { + init_func_ = init_func; + update_func_ = update_func; + draw_func_ = draw_func; + shut_down_func_ = shut_down_func; + } + + virtual void Render(float elapsed_sec) { + if (update_func_) update_func_(&context_, elapsed_sec); + draw_func_(&context_); } private: ESContext context_; UserData user_data_; + + // Callback functions. + InitFunc* init_func_; + UpdateFunc* update_func_; + DrawFunc* draw_func_; + ShutDownFunc* shut_down_func_; + DISALLOW_COPY_AND_ASSIGN(Example); }; -// Many examples do need to update anything and hence do not provide an -// update function. This no-op function can be used for such examples. -inline void NoOpUpdateFunc(ESContext* context, float elapsed_sec) {} - } // namespace gles2_book } // namespace demos } // namespace gpu diff --git a/gpu/demos/hello_triangle/main.cc b/gpu/demos/gles2_book/hello_triangle.cc index 3e45ffc..806a0dd 100644 --- a/gpu/demos/hello_triangle/main.cc +++ b/gpu/demos/gles2_book/hello_triangle.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -7,25 +7,29 @@ // example is to demonstrate the basic concepts of // OpenGL ES 2.0 rendering. +#include "gpu/demos/framework/demo_factory.h" #include "gpu/demos/gles2_book/example.h" #include "third_party/gles2_book/Chapter_2/Hello_Triangle/Hello_Triangle.h" namespace gpu { namespace demos { + namespace gles2_book { -typedef Example<HTUserData, - htInit, - NoOpUpdateFunc, - htDraw, - htShutDown> HelloTriangle; -} // namespace gles2_book -} // namespace demos -} // namespace gpu +class HelloTriangle : public Example<HTUserData> { + public: + HelloTriangle() { + RegisterCallbacks(htInit, NULL, htDraw, htShutDown); + } -int main(int argc, char *argv[]) { - gpu::demos::gles2_book::HelloTriangle demo; - CHECK(demo.Init()); + const wchar_t* Title() const { + return L"Hello Triangle"; + } +}; +} // namespace gles2_book - demo.MainLoop(); - return EXIT_SUCCESS; +Demo* CreateDemo() { + return new gles2_book::HelloTriangle(); } + +} // namespace demos +} // namespace gpu diff --git a/gpu/demos/pepper_gpu_demo.html b/gpu/demos/pepper_gpu_demo.html new file mode 100644 index 0000000..8be4e57 --- /dev/null +++ b/gpu/demos/pepper_gpu_demo.html @@ -0,0 +1,12 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Pepper GPU Demo</title> +</head> + +<body style="background-color:Silver"> + +<h1>Pepper GPU Demo</h1> +<object id="plugin" type="pepper-application/x-gpu-demo" width="512" height="512" /> + +</body> +</html> |