|
|
@@ -1,279 +1,279 @@
|
|
|
-// Filename: shader.cxx
|
|
|
-// Created by: jyelon (Sep05)
|
|
|
-//
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-//
|
|
|
-// PANDA 3D SOFTWARE
|
|
|
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
|
|
-//
|
|
|
-// All use of this software is subject to the terms of the Panda 3d
|
|
|
-// Software license. You should have received a copy of this license
|
|
|
-// along with this source code; you will also find a current copy of
|
|
|
-// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
|
|
-//
|
|
|
-// To contact the maintainers of this program write to
|
|
|
-// [email protected] .
|
|
|
-//
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
-#include "pandabase.h"
|
|
|
-#include "shader.h"
|
|
|
-
|
|
|
-TypeHandle Shader::_type_handle;
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::Constructor
|
|
|
-// Access: Public
|
|
|
-// Description: Construct a Shader.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-Shader::
|
|
|
-Shader(const string &text, const string &file) {
|
|
|
- _text = text;
|
|
|
- _file = file;
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::Destructor
|
|
|
-// Access: Public
|
|
|
-// Description: Delete the compiled code, if it exists.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-Shader::
|
|
|
-~Shader() {
|
|
|
- release_all();
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::parse_init
|
|
|
-// Access: Public
|
|
|
-// Description: Set a 'parse pointer' to the beginning of the shader.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void Shader::
|
|
|
-parse_init(void) {
|
|
|
- _parse = 0;
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::parse_line
|
|
|
-// Access: Public
|
|
|
-// Description: Parse a line of text. If 'lt' is true, trim blanks
|
|
|
-// from the left end of the line. If 'rt' is true, trim
|
|
|
-// blanks from the right end (the newline is always
|
|
|
-// trimmed).
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void Shader::
|
|
|
-parse_line(string &result, bool lt, bool rt) {
|
|
|
- int len = _text.size();
|
|
|
- int head = _parse;
|
|
|
- int tail = head;
|
|
|
- while ((tail < len) && (_text[tail] != '\n')) tail++;
|
|
|
- if (tail < len) {
|
|
|
- _parse = tail+1;
|
|
|
- } else {
|
|
|
- _parse = tail;
|
|
|
- }
|
|
|
- if (lt) {
|
|
|
- while ((head < tail)&&(isspace(_text[head]))) head++;
|
|
|
- while ((tail > head)&&(isspace(_text[tail-1]))) tail--;
|
|
|
- }
|
|
|
- result = _text.substr(head, tail-head);
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::parse_upto
|
|
|
-// Access: Public
|
|
|
-// Description: Parse lines until you read a line that matches the
|
|
|
-// specified pattern. Returns all the preceding lines,
|
|
|
-// and if the include flag is set, returns the final
|
|
|
-// line as well.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void Shader::
|
|
|
-parse_upto(string &result, string pattern, bool include) {
|
|
|
- int start = _parse;
|
|
|
- int last = _parse;
|
|
|
- while (true) {
|
|
|
- string t;
|
|
|
- parse_line(t, true, true);
|
|
|
- if (t == pattern) break;
|
|
|
- last = _parse;
|
|
|
- }
|
|
|
- if (include) {
|
|
|
- result = _text.substr(start, _parse - start);
|
|
|
- } else {
|
|
|
- result = _text.substr(start, last - start);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::parse_rest
|
|
|
-// Access: Public
|
|
|
-// Description: Returns the rest of the text from the current
|
|
|
-// parse location.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void Shader::
|
|
|
-parse_rest(string &result) {
|
|
|
- result = _text.substr(_parse, _text.size() - _parse);
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::parse_eof
|
|
|
-// Access: Public
|
|
|
-// Description: Returns true if the parse pointer is at the end of
|
|
|
-// the shader.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-bool Shader::
|
|
|
-parse_eof(void) {
|
|
|
- return (int)_text.size() == _parse;
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::arg_index
|
|
|
-// Access: Public
|
|
|
-// Description: Allocates an integer index to the given
|
|
|
-// shader parameter name.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-int Shader::
|
|
|
-arg_index(const string &id) {
|
|
|
- for (int i=0; i<(int)(_args.size()); i++)
|
|
|
- if (_args[i] == id)
|
|
|
- return i;
|
|
|
- _args.push_back(id);
|
|
|
- return _args.size() - 1;
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::prepare
|
|
|
-// Access: Published
|
|
|
-// Description: Indicates that the shader should be enqueued to be
|
|
|
-// prepared in the indicated prepared_objects at the
|
|
|
-// beginning of the next frame. This will ensure the
|
|
|
-// texture is already loaded into texture memory if it
|
|
|
-// is expected to be rendered soon.
|
|
|
-//
|
|
|
-// Use this function instead of prepare_now() to preload
|
|
|
-// textures from a user interface standpoint.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void Shader::
|
|
|
-prepare(PreparedGraphicsObjects *prepared_objects) {
|
|
|
- prepared_objects->enqueue_shader(this);
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::release
|
|
|
-// Access: Published
|
|
|
-// Description: Frees the texture context only on the indicated object,
|
|
|
-// if it exists there. Returns true if it was released,
|
|
|
-// false if it had not been prepared.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-bool Shader::
|
|
|
-release(PreparedGraphicsObjects *prepared_objects) {
|
|
|
- Contexts::iterator ci;
|
|
|
- ci = _contexts.find(prepared_objects);
|
|
|
- if (ci != _contexts.end()) {
|
|
|
- ShaderContext *sc = (*ci).second;
|
|
|
- if (sc != (ShaderContext *)NULL) {
|
|
|
- prepared_objects->release_shader(sc);
|
|
|
- } else {
|
|
|
- _contexts.erase(ci);
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- // Maybe it wasn't prepared yet, but it's about to be.
|
|
|
- return prepared_objects->dequeue_shader(this);
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::prepare_now
|
|
|
-// Access: Public
|
|
|
-// Description: Creates a context for the texture on the particular
|
|
|
-// GSG, if it does not already exist. Returns the new
|
|
|
-// (or old) ShaderContext. This assumes that the
|
|
|
-// GraphicsStateGuardian is the currently active
|
|
|
-// rendering context and that it is ready to accept new
|
|
|
-// textures. If this is not necessarily the case, you
|
|
|
-// should use prepare() instead.
|
|
|
-//
|
|
|
-// Normally, this is not called directly except by the
|
|
|
-// GraphicsStateGuardian; a texture does not need to be
|
|
|
-// explicitly prepared by the user before it may be
|
|
|
-// rendered.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-ShaderContext *Shader::
|
|
|
-prepare_now(PreparedGraphicsObjects *prepared_objects,
|
|
|
- GraphicsStateGuardianBase *gsg) {
|
|
|
- Contexts::const_iterator ci;
|
|
|
- ci = _contexts.find(prepared_objects);
|
|
|
- if (ci != _contexts.end()) {
|
|
|
- return (*ci).second;
|
|
|
- }
|
|
|
-
|
|
|
- ShaderContext *tc = prepared_objects->prepare_shader_now(this, gsg);
|
|
|
- _contexts[prepared_objects] = tc;
|
|
|
-
|
|
|
- return tc;
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::clear_prepared
|
|
|
-// Access: Private
|
|
|
-// Description: Removes the indicated PreparedGraphicsObjects table
|
|
|
-// from the Shader's table, without actually releasing
|
|
|
-// the texture. This is intended to be called only from
|
|
|
-// PreparedGraphicsObjects::release_texture(); it should
|
|
|
-// never be called by user code.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void Shader::
|
|
|
-clear_prepared(PreparedGraphicsObjects *prepared_objects) {
|
|
|
- Contexts::iterator ci;
|
|
|
- ci = _contexts.find(prepared_objects);
|
|
|
- if (ci != _contexts.end()) {
|
|
|
- _contexts.erase(ci);
|
|
|
- } else {
|
|
|
- // If this assertion fails, clear_prepared() was given a
|
|
|
- // prepared_objects which the texture didn't know about.
|
|
|
- nassertv(false);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::release_all
|
|
|
-// Access: Published
|
|
|
-// Description: Frees the context allocated on all objects for which
|
|
|
-// the texture has been declared. Returns the number of
|
|
|
-// contexts which have been freed.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-int Shader::
|
|
|
-release_all() {
|
|
|
- // We have to traverse a copy of the _contexts list, because the
|
|
|
- // PreparedGraphicsObjects object will call clear_prepared() in response
|
|
|
- // to each release_texture(), and we don't want to be modifying the
|
|
|
- // _contexts list while we're traversing it.
|
|
|
- Contexts temp = _contexts;
|
|
|
- int num_freed = (int)_contexts.size();
|
|
|
-
|
|
|
- Contexts::const_iterator ci;
|
|
|
- for (ci = temp.begin(); ci != temp.end(); ++ci) {
|
|
|
- PreparedGraphicsObjects *prepared_objects = (*ci).first;
|
|
|
- ShaderContext *sc = (*ci).second;
|
|
|
- if (sc != (ShaderContext *)NULL) {
|
|
|
- prepared_objects->release_shader(sc);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // There might still be some outstanding contexts in the map, if
|
|
|
- // there were any NULL pointers there. Eliminate them.
|
|
|
- _contexts.clear();
|
|
|
-
|
|
|
- return num_freed;
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Shader::register_with_read_factory
|
|
|
-// Access: Public, Static
|
|
|
-// Description: Factory method to generate a Shader object
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void Shader::
|
|
|
-register_with_read_factory() {
|
|
|
- // IMPLEMENT ME
|
|
|
-}
|
|
|
-
|
|
|
+// Filename: shader.cxx
|
|
|
+// Created by: jyelon (Sep05)
|
|
|
+//
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+//
|
|
|
+// PANDA 3D SOFTWARE
|
|
|
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
|
|
+//
|
|
|
+// All use of this software is subject to the terms of the Panda 3d
|
|
|
+// Software license. You should have received a copy of this license
|
|
|
+// along with this source code; you will also find a current copy of
|
|
|
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
|
|
+//
|
|
|
+// To contact the maintainers of this program write to
|
|
|
+// [email protected] .
|
|
|
+//
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+#include "pandabase.h"
|
|
|
+#include "shader.h"
|
|
|
+
|
|
|
+TypeHandle Shader::_type_handle;
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::Constructor
|
|
|
+// Access: Public
|
|
|
+// Description: Construct a Shader.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+Shader::
|
|
|
+Shader(const string &text, const string &file) {
|
|
|
+ _text = text;
|
|
|
+ _file = file;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::Destructor
|
|
|
+// Access: Public
|
|
|
+// Description: Delete the compiled code, if it exists.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+Shader::
|
|
|
+~Shader() {
|
|
|
+ release_all();
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::parse_init
|
|
|
+// Access: Public
|
|
|
+// Description: Set a 'parse pointer' to the beginning of the shader.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Shader::
|
|
|
+parse_init(void) {
|
|
|
+ _parse = 0;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::parse_line
|
|
|
+// Access: Public
|
|
|
+// Description: Parse a line of text. If 'lt' is true, trim blanks
|
|
|
+// from the left end of the line. If 'rt' is true, trim
|
|
|
+// blanks from the right end (the newline is always
|
|
|
+// trimmed).
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Shader::
|
|
|
+parse_line(string &result, bool lt, bool rt) {
|
|
|
+ int len = _text.size();
|
|
|
+ int head = _parse;
|
|
|
+ int tail = head;
|
|
|
+ while ((tail < len) && (_text[tail] != '\n')) tail++;
|
|
|
+ if (tail < len) {
|
|
|
+ _parse = tail+1;
|
|
|
+ } else {
|
|
|
+ _parse = tail;
|
|
|
+ }
|
|
|
+ if (lt) {
|
|
|
+ while ((head < tail)&&(isspace(_text[head]))) head++;
|
|
|
+ while ((tail > head)&&(isspace(_text[tail-1]))) tail--;
|
|
|
+ }
|
|
|
+ result = _text.substr(head, tail-head);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::parse_upto
|
|
|
+// Access: Public
|
|
|
+// Description: Parse lines until you read a line that matches the
|
|
|
+// specified pattern. Returns all the preceding lines,
|
|
|
+// and if the include flag is set, returns the final
|
|
|
+// line as well.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Shader::
|
|
|
+parse_upto(string &result, string pattern, bool include) {
|
|
|
+ int start = _parse;
|
|
|
+ int last = _parse;
|
|
|
+ while (true) {
|
|
|
+ string t;
|
|
|
+ parse_line(t, true, true);
|
|
|
+ if (t == pattern) break;
|
|
|
+ last = _parse;
|
|
|
+ }
|
|
|
+ if (include) {
|
|
|
+ result = _text.substr(start, _parse - start);
|
|
|
+ } else {
|
|
|
+ result = _text.substr(start, last - start);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::parse_rest
|
|
|
+// Access: Public
|
|
|
+// Description: Returns the rest of the text from the current
|
|
|
+// parse location.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Shader::
|
|
|
+parse_rest(string &result) {
|
|
|
+ result = _text.substr(_parse, _text.size() - _parse);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::parse_eof
|
|
|
+// Access: Public
|
|
|
+// Description: Returns true if the parse pointer is at the end of
|
|
|
+// the shader.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool Shader::
|
|
|
+parse_eof(void) {
|
|
|
+ return (int)_text.size() == _parse;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::arg_index
|
|
|
+// Access: Public
|
|
|
+// Description: Allocates an integer index to the given
|
|
|
+// shader parameter name.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+int Shader::
|
|
|
+arg_index(const string &id) {
|
|
|
+ for (int i=0; i<(int)(_args.size()); i++)
|
|
|
+ if (_args[i] == id)
|
|
|
+ return i;
|
|
|
+ _args.push_back(id);
|
|
|
+ return _args.size() - 1;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::prepare
|
|
|
+// Access: Published
|
|
|
+// Description: Indicates that the shader should be enqueued to be
|
|
|
+// prepared in the indicated prepared_objects at the
|
|
|
+// beginning of the next frame. This will ensure the
|
|
|
+// texture is already loaded into texture memory if it
|
|
|
+// is expected to be rendered soon.
|
|
|
+//
|
|
|
+// Use this function instead of prepare_now() to preload
|
|
|
+// textures from a user interface standpoint.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Shader::
|
|
|
+prepare(PreparedGraphicsObjects *prepared_objects) {
|
|
|
+ prepared_objects->enqueue_shader(this);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::release
|
|
|
+// Access: Published
|
|
|
+// Description: Frees the texture context only on the indicated object,
|
|
|
+// if it exists there. Returns true if it was released,
|
|
|
+// false if it had not been prepared.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool Shader::
|
|
|
+release(PreparedGraphicsObjects *prepared_objects) {
|
|
|
+ Contexts::iterator ci;
|
|
|
+ ci = _contexts.find(prepared_objects);
|
|
|
+ if (ci != _contexts.end()) {
|
|
|
+ ShaderContext *sc = (*ci).second;
|
|
|
+ if (sc != (ShaderContext *)NULL) {
|
|
|
+ prepared_objects->release_shader(sc);
|
|
|
+ } else {
|
|
|
+ _contexts.erase(ci);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Maybe it wasn't prepared yet, but it's about to be.
|
|
|
+ return prepared_objects->dequeue_shader(this);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::prepare_now
|
|
|
+// Access: Public
|
|
|
+// Description: Creates a context for the texture on the particular
|
|
|
+// GSG, if it does not already exist. Returns the new
|
|
|
+// (or old) ShaderContext. This assumes that the
|
|
|
+// GraphicsStateGuardian is the currently active
|
|
|
+// rendering context and that it is ready to accept new
|
|
|
+// textures. If this is not necessarily the case, you
|
|
|
+// should use prepare() instead.
|
|
|
+//
|
|
|
+// Normally, this is not called directly except by the
|
|
|
+// GraphicsStateGuardian; a texture does not need to be
|
|
|
+// explicitly prepared by the user before it may be
|
|
|
+// rendered.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+ShaderContext *Shader::
|
|
|
+prepare_now(PreparedGraphicsObjects *prepared_objects,
|
|
|
+ GraphicsStateGuardianBase *gsg) {
|
|
|
+ Contexts::const_iterator ci;
|
|
|
+ ci = _contexts.find(prepared_objects);
|
|
|
+ if (ci != _contexts.end()) {
|
|
|
+ return (*ci).second;
|
|
|
+ }
|
|
|
+
|
|
|
+ ShaderContext *tc = prepared_objects->prepare_shader_now(this, gsg);
|
|
|
+ _contexts[prepared_objects] = tc;
|
|
|
+
|
|
|
+ return tc;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::clear_prepared
|
|
|
+// Access: Private
|
|
|
+// Description: Removes the indicated PreparedGraphicsObjects table
|
|
|
+// from the Shader's table, without actually releasing
|
|
|
+// the texture. This is intended to be called only from
|
|
|
+// PreparedGraphicsObjects::release_texture(); it should
|
|
|
+// never be called by user code.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Shader::
|
|
|
+clear_prepared(PreparedGraphicsObjects *prepared_objects) {
|
|
|
+ Contexts::iterator ci;
|
|
|
+ ci = _contexts.find(prepared_objects);
|
|
|
+ if (ci != _contexts.end()) {
|
|
|
+ _contexts.erase(ci);
|
|
|
+ } else {
|
|
|
+ // If this assertion fails, clear_prepared() was given a
|
|
|
+ // prepared_objects which the texture didn't know about.
|
|
|
+ nassertv(false);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::release_all
|
|
|
+// Access: Published
|
|
|
+// Description: Frees the context allocated on all objects for which
|
|
|
+// the texture has been declared. Returns the number of
|
|
|
+// contexts which have been freed.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+int Shader::
|
|
|
+release_all() {
|
|
|
+ // We have to traverse a copy of the _contexts list, because the
|
|
|
+ // PreparedGraphicsObjects object will call clear_prepared() in response
|
|
|
+ // to each release_texture(), and we don't want to be modifying the
|
|
|
+ // _contexts list while we're traversing it.
|
|
|
+ Contexts temp = _contexts;
|
|
|
+ int num_freed = (int)_contexts.size();
|
|
|
+
|
|
|
+ Contexts::const_iterator ci;
|
|
|
+ for (ci = temp.begin(); ci != temp.end(); ++ci) {
|
|
|
+ PreparedGraphicsObjects *prepared_objects = (*ci).first;
|
|
|
+ ShaderContext *sc = (*ci).second;
|
|
|
+ if (sc != (ShaderContext *)NULL) {
|
|
|
+ prepared_objects->release_shader(sc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // There might still be some outstanding contexts in the map, if
|
|
|
+ // there were any NULL pointers there. Eliminate them.
|
|
|
+ _contexts.clear();
|
|
|
+
|
|
|
+ return num_freed;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Shader::register_with_read_factory
|
|
|
+// Access: Public, Static
|
|
|
+// Description: Factory method to generate a Shader object
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Shader::
|
|
|
+register_with_read_factory() {
|
|
|
+ // IMPLEMENT ME
|
|
|
+}
|
|
|
+
|