| /* |
| * Copyright 2009, Google Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| |
| // This file contains the class definition of the o3d::Client, |
| // the main entry point to O3D. |
| |
| #ifndef O3D_CORE_CROSS_CLIENT_H_ |
| #define O3D_CORE_CROSS_CLIENT_H_ |
| |
| #include <build/build_config.h> |
| #include <map> |
| #include <ostream> |
| #include <sstream> |
| #include <string> |
| #include <vector> |
| |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "core/cross/service_dependency.h" |
| #include "core/cross/error_status.h" |
| #include "core/cross/draw_list_manager.h" |
| #include "core/cross/counter_manager.h" |
| #include "core/cross/object_manager.h" |
| #include "core/cross/semantic_manager.h" |
| #include "core/cross/transformation_context.h" |
| #include "core/cross/render_node.h" |
| #include "core/cross/callback.h" |
| #include "core/cross/event.h" |
| #include "core/cross/event_callback.h" |
| #include "core/cross/event_manager.h" |
| #include "core/cross/lost_resource_callback.h" |
| #include "core/cross/render_event.h" |
| #include "core/cross/render_surface.h" |
| #include "core/cross/tick_event.h" |
| #include "core/cross/timer.h" |
| #include "core/cross/timingtable.h" |
| #include "core/cross/transform.h" |
| |
| namespace o3d { |
| class MessageQueue; |
| class Profiler; |
| class State; |
| class Pack; |
| |
| // The Client class is the main point of entry to O3D. It defines methods |
| // for creating and deleting packs and internal use only methods for creating |
| // most objects. Each new object created by the Client is assigned a unique ID |
| // which can be used to efficiently retrieve the object using the appropriate |
| // Get*ById() method. |
| // |
| // The Client has a root transform for the transform graph and a root render |
| // node for the render graph. |
| class Client { |
| friend class ObjectBase; |
| friend class ParamObject; |
| |
| public: |
| |
| explicit Client(ServiceLocator* service_locator); |
| ~Client(); |
| |
| typedef NonRecursiveCallback1Manager<const RenderEvent&> |
| RenderCallbackManager; |
| typedef RenderCallbackManager::CallbackType RenderCallback; |
| |
| // Name of the default pack that the default rendergraph rendernodes belong |
| // to. |
| static const char* kDefaultPackName; |
| |
| Id id() const { |
| return id_; |
| } |
| |
| // Sets the renderer to be used for all platform-specific graphics |
| // methods and sets up the default rendergraph |
| void Init(); |
| |
| // Cleansup certain things in preparation for unloading the plugin. |
| // This is for Javascript because there are certain conditions, the Render |
| // callback for example, which can cause a javascript error in the browser |
| // while the page is being unloaded. This function, if called during |
| // window.onunload, handles those cases. |
| void Cleanup(); |
| |
| // Pack methods -------------------------- |
| |
| // Creates a pack object, and registers it within the Client's internal |
| // dictionary strutures. Note that multiple packs may share the same name. |
| // The system does not enforce pack name uniqueness. |
| // Returns: |
| // A smart-pointer reference to the newly created pack object. |
| Pack* CreatePack(); |
| |
| // Node methods -------------------------- |
| |
| // Returns the transform graph root transform |
| // Parameters: |
| // None |
| // Returns: |
| // A pointer to the transform graph root Transform |
| inline Transform* root() const { |
| return root_.Get(); |
| } |
| |
| // RenderNode methods -------------------------- |
| |
| enum RenderMode { |
| RENDERMODE_CONTINUOUS, // Draw as often as possible up to refresh rate. |
| RENDERMODE_ON_DEMAND, // Draw once, then only when the OS requests it |
| // (like uncovering part of a window.) |
| }; |
| |
| RenderMode render_mode() const { |
| return render_mode_; |
| } |
| |
| void set_render_mode(RenderMode render_mode); |
| |
| // Returns the rendergraph root render node. |
| // Parameters: |
| // None. |
| // Returns: |
| // A pointer to the rendergraph root rendernode. |
| inline RenderNode* render_graph_root() const { |
| return rendergraph_root_; |
| } |
| |
| // Searches the entire Client's rendernode dictionary for rendernodes that |
| // match the given name. It will find rendernodes created by the Client |
| // regardless of whether or not they are part of the rendergraph. |
| // Parameters: |
| // name: Node name to look for. |
| // render_nodes: RenderNodeArray to receive list of nodes. It anything is in |
| // the array will be cleared. |
| void GetRenderNodesFast(const String& name, |
| RenderNodeArray* render_nodes) const; |
| |
| // Renders a subtree of the rendergraph. |
| // Parameters: |
| // tree_root: The root of the subtree to be drawn. |
| // Returns: |
| // Nothing |
| void RenderTree(RenderNode *tree_root); |
| |
| // Sets the render callback. |
| // NOTE: The client takes ownership of the RenderCallback you pass in. It will |
| // be deleted if you call SetRenderCallback a second time or if you call |
| // ClearRenderCallback |
| // |
| // Parameters: |
| // render_callback: RenderCallback to call each frame. |
| void SetRenderCallback(RenderCallback* render_callback); |
| |
| // Clears the render callback |
| // NOTE: The client takes ownership of the RenderCallback you pass in to |
| // SetRenderCallback. It will be deleted if you call SetRenderCallback a |
| // second time or if you call ClearRenderCallback |
| void ClearRenderCallback(); |
| |
| // Sets the callback for a events of a supplied type. |
| // NOTE: The client takes ownership of the EventCallback you pass in. It will |
| // be deleted if you call SetEventCallback a second time for the same event |
| // type or if you call ClearEventCallback for that type. |
| // |
| // Parameters: |
| // event_callback: EventCallback to call each time an event of the right |
| // type occurs. |
| // type: Type of event this callback handles. |
| void SetEventCallback(Event::Type type, EventCallback* render_callback); |
| void SetEventCallback(String type_name, EventCallback* render_callback); |
| |
| // Clears the callback for events of a given type. |
| void ClearEventCallback(Event::Type type); |
| void ClearEventCallback(String type_name); |
| |
| // Automatically drops some events to throttle event bandwidth. |
| void AddEventToQueue(const Event& event); |
| // Adds a resize event to the queue. |
| void SendResizeEvent(int width, int height, bool fullscreen); |
| |
| // Sets the lost resources callback. |
| // NOTE: The client takes ownership of the LostResourcesCallback you pass in. |
| // It will be deleted if you call SetLostResourcesCallback a second time or if |
| // you call ClearLostResourcesCallback |
| // |
| // Parameters: |
| // callback: LostResourcesCallback to call each frame. |
| void SetLostResourcesCallback(LostResourcesCallback* callback); |
| |
| // Clears the lost resources callback |
| // NOTE: The client takes ownership of the LostResourcesCallback you pass in |
| // to SetLostResourcesCallback. It will be deleted if you call |
| // SetLostResourcesCallback a second time or if you call |
| // ClearLostResourcesCallback. |
| void ClearLostResourcesCallback(); |
| |
| // Forces a render of the current scene if the current render mode is |
| // RENDERMODE_ON_DEMAND. |
| void Render(); |
| |
| // Sets the post render callback. |
| // NOTE: The client takes ownership of the RenderCallback you pass in. It will |
| // be deleted if you call SetPostRenderCallback a second time or if you call |
| // ClearPostRenderCallback |
| // |
| // Parameters: |
| // post_render_callback: RenderCallback to call at the end of |
| // the render cycle in each frame. |
| void SetPostRenderCallback(RenderCallback* post_render_callback); |
| |
| // Clears the post render callback |
| // NOTE: The client takes ownership of the RenderCallback you pass in to |
| // SetPostRenderCallback. It will be deleted if you call post |
| // SetRenderCallback a second time or if you call ClearRenderCallback. |
| void ClearPostRenderCallback(); |
| |
| // Updates the current state of the objects handled by the Client and |
| // processes any messages found in the message queue then renders the client. |
| // This is the function anything hosting the client, like a plugin, should |
| // call to render. |
| // Parameters: |
| // send_callback : whether to make the javascript render callback. |
| // Generally you want to pass true, but if the render is happening |
| // in non-windowed mode (eg on a Mac) and is in response to an update |
| // event rather than a timer, it can be useful to pass false to prevent |
| // the javascript code triggering another update and causing an infinite |
| // calback loop. Case in point is the custom camera example, which |
| // modifies some HTML form text fields on render callback, which on |
| // Firefox causes a plugin invalidation and round and round we would |
| // go. |
| void RenderClient(bool send_callback); |
| |
| // In some situations (on Mac OS X at least) calling the user's |
| // render callback can cause OS events to be dispatched which cause |
| // the plugin to become reentrant. Detect this at a higher level. |
| bool IsRendering(); |
| |
| // Needs either ONDEMAND or CONTINOUS render. |
| bool NeedsRender(); |
| |
| // If Renderer::max_fps has been set in RENDERMODE_CONTINUOUS mode, we don't |
| // draw on each tick but just let new textures drive the rendering. There is |
| // only one exception: if we haven't received any new textures for a while, we |
| // still need to draw in order to trigger rendering callback. Since there |
| // might be some UI depends on rendering callback. |
| // This function determines if this has happened and if we need a draw. |
| bool NeedsContinuousRender(); |
| |
| // Sets the texture to use when a Texture or Sampler is missing while |
| // rendering. If you set it to NULL you'll get an error if you try to render |
| // something that is missing a needed Texture, Sampler or ParamSampler |
| // Parameters: |
| // texture: texture to use for missing texture or NULL. |
| void SetErrorTexture(Texture* texture); |
| |
| // Tick Methods ---------------------------- |
| |
| typedef NonRecursiveCallback1Manager<const o3d::TickEvent&> |
| TickCallbackManager; |
| typedef TickCallbackManager::CallbackType TickCallback; |
| |
| // Sets the tick callback. |
| // NOTE: The client takes ownership of the TickCallback you pass in. It will |
| // be deleted if you call SetTickCallback a second time or if you call |
| // ClearTickCallback. |
| // |
| // Parameters: |
| // tick_callback: TickCallback to call each time the client processes a |
| // tick. |
| void SetTickCallback(TickCallback* tick_callback); |
| |
| // Clears the tick callback NOTE: The client takes ownership of the |
| // TickCallback you pass in to SetTickCallback. It will be deleted if you call |
| // SetTickCallback a second time or if you call ClearTickCallback. |
| void ClearTickCallback(); |
| |
| // Tick the client. This method is called by the plugin to give the client |
| // a chance to process NaCl messages and update animation. |
| // Returns: |
| // true if message check was ok. |
| bool Tick(); |
| |
| // Indicates whether a call to Tick() is in progress. This is needed |
| // to avoid reentrancy problems on some platforms. |
| bool IsTicking() const { |
| return is_ticking_; |
| } |
| |
| // Searches in the Client for an object by its id. This function is for |
| // Javascript. |
| // Parameters: |
| // id: id of object to look for. |
| // Returns: |
| // Pointer to the object or NULL if not found. |
| ObjectBase* GetObjectById(Id id) const { |
| return object_manager_->GetObjectById(id); |
| } |
| |
| // Searches the Client for objects of a particular name and type. |
| // This function is for Javascript. |
| // Parameters: |
| // name: name of object to look for. |
| // type_name: name of class to look for. |
| // Returns: |
| // Array of raw pointers to the found objects. |
| ObjectBaseArray GetObjects(const String& name, |
| const String& type_name) const { |
| return object_manager_->GetObjects(name, type_name); |
| } |
| |
| // Searches by id for an Object created by the Client. To search |
| // for an object regardless of type use: |
| // Client::GetById<ObjectBase>(obj_id) |
| // To search for an object of a specific type use: |
| // Client::GetById<Type>(obj_id) |
| // for example, to search for Transform use: |
| // Client::GetById<Transform>(transform_id) |
| // Parameters: |
| // id: Unique id of the object to search for |
| // Returns: |
| // Pointer to the object with matching id or NULL if no object is found |
| template<class T> T* GetById(Id id) const { |
| return object_manager_->GetById<T>(id); |
| } |
| |
| // Search the client for all objects of a certain class |
| // Returns: |
| // Array of Pointers to the requested class. |
| template<typename T> |
| std::vector<T*> GetByClass() const { |
| return object_manager_->GetByClass<T>(); |
| } |
| |
| // Search the client for all objects of a certain class |
| // Parameters: |
| // class_type_name: the Class of the object. It is okay to pass base types |
| // for example Node::GetApparentClass()->name will return |
| // both Transforms and Shapes. |
| // Returns: |
| // Array of Object Pointers. |
| ObjectBaseArray GetObjectsByClassName(const String& class_type_name) const { |
| return object_manager_->GetObjectsByClassName(class_type_name); |
| } |
| |
| // Returns the socket address of the IMC message queue associated with the |
| // Client. |
| String GetMessageQueueAddress() const; |
| |
| // Error Methods ---------------- |
| |
| typedef Callback1<const String&> ErrorCallback; |
| |
| // Sets the error callback. NOTE: The client takes ownership of the |
| // ErrorCallback you pass in. It will be deleted if you call SetErrorCallback |
| // a second time or if you call ClearErrorCallback. |
| // |
| // Parameters: |
| // error_callback: ErrorCallback to call each time the client gets |
| // an error. |
| void SetErrorCallback(ErrorCallback* error_callback); |
| |
| // Clears the Error callback NOTE: The client takes ownership of the |
| // ErrorCallback you pass in to SetErrorCallback. It will be deleted if you |
| // call SetErrorCallback a second time or if you call ClearErrorCallback. |
| void ClearErrorCallback(); |
| |
| // Gets the last reported error. |
| const String& GetLastError() const; |
| |
| // Clears the stored last error. |
| void ClearLastError(); |
| |
| // Parameter methods ------------------ |
| |
| // Marks all parameters as so they will get re-evaluated |
| void InvalidateAllParameters(); |
| |
| // Profiling methods ------------------- |
| |
| // Starts the timer ticking for the code range identified by key. |
| void ProfileStart(const std::string& key); |
| |
| // Stops the timer for the code range identified by key. |
| void ProfileStop(const std::string& key); |
| |
| // Resets the profiler, clearing out all data. |
| void ProfileReset(); |
| |
| // Dumps all profiler state to a string. |
| String ProfileToString(); |
| |
| // Reutrns a data: URL of the client area in png format. |
| String ToDataURL(); |
| |
| // This class is intended to be used on the stack, such that the variable gets |
| // incremented on scope entry and decremented on scope exit. It's currently |
| // used in WindowProc to determine if we're reentrant or not, but may be |
| // needed on other platforms as well. |
| class ScopedIncrement { |
| public: |
| explicit ScopedIncrement(Client *client) { |
| DCHECK(client); |
| client_ = client; |
| ++client_->calls_; |
| DCHECK_GT(client_->calls_, 0); |
| } |
| int get() { |
| DCHECK(client_); // Don't call this after decrement! |
| return client_->calls_; |
| } |
| void decrement() { |
| if (client_) { |
| DCHECK_GT(client_->calls_, 0); |
| --client_->calls_; |
| client_ = NULL; |
| } |
| } |
| ~ScopedIncrement() { |
| decrement(); |
| } |
| private: |
| Client *client_; |
| DISALLOW_COPY_AND_ASSIGN(ScopedIncrement); |
| }; |
| |
| // Offscreen rendering methods ------------------- |
| |
| // Sets up this Client so that RenderClient will cause the rendering |
| // results to go into the given surfaces. |
| void SetOffscreenRenderingSurfaces( |
| RenderSurface::Ref surface, |
| RenderDepthStencilSurface::Ref depth_surface); |
| |
| private: |
| // Renders the client. |
| void RenderClientInner(bool present, bool send_callback); |
| |
| // Gets a screenshot. |
| String GetScreenshotAsDataURL(); |
| |
| // MessageQueue that allows external code to communicate with the Client. |
| scoped_ptr<MessageQueue> message_queue_; |
| |
| ServiceLocator* service_locator_; |
| ServiceDependency<ObjectManager> object_manager_; |
| ErrorStatus error_status_; |
| DrawListManager draw_list_manager_; |
| CounterManager counter_manager_; |
| TransformationContext transformation_context_; |
| SemanticManager semantic_manager_; |
| ServiceDependency<Profiler> profiler_; |
| ServiceDependency<Renderer> renderer_; |
| ServiceDependency<EvaluationCounter> evaluation_counter_; |
| |
| // RenderTree was called. |
| bool render_tree_called_; |
| |
| // Render mode. |
| RenderMode render_mode_; |
| |
| // Used for rendering control |
| bool texture_on_hold_; |
| |
| // Render Callbacks. |
| RenderCallbackManager render_callback_manager_; |
| |
| RenderCallbackManager post_render_callback_manager_; |
| |
| // Render Event to pass to the render callback. |
| RenderEvent render_event_; |
| |
| // This class holds on to all the handlers and the event queue for standard |
| // JavaScript IO events. |
| EventManager event_manager_; |
| |
| // Timer for getting the elapsed time between render updates. |
| ElapsedTimeTimer render_elapsed_time_timer_; |
| |
| // Tick Callback. |
| TickCallbackManager tick_callback_manager_; |
| |
| // Tick Event to pass to the tick callback. |
| TickEvent tick_event_; |
| |
| // Timer for getting the elapsed time between tick updates. |
| ElapsedTimeTimer tick_elapsed_time_timer_; |
| |
| // Whether a call to Tick() is currently active. |
| bool is_ticking_; |
| |
| // Used to gather render time from mulitple RenderTree calls. |
| float total_time_to_render_; |
| |
| // Time used for tick and message processing. |
| float last_tick_time_; |
| |
| // Number of ticks since last reset. |
| int tick_count_; |
| |
| // Reference to global transform graph root for Client. |
| Transform::Ref root_; |
| |
| // Global Render Graph root for Client. |
| RenderNode::Ref rendergraph_root_; |
| |
| ParamObject::Ref sas_param_object_; |
| |
| // The id of the client. |
| Id id_; |
| |
| int calls_; // Used to check reentrancy along with ScopedIncrement. |
| |
| RenderSurface::Ref offscreen_render_surface_; |
| RenderDepthStencilSurface::Ref offscreen_depth_render_surface_; |
| |
| DISALLOW_COPY_AND_ASSIGN(Client); |
| }; // Client |
| |
| } // namespace o3d |
| |
| #endif // O3D_CORE_CROSS_CLIENT_H_ |