Platform/GFX/WebGL/Contribute/Extensions: Difference between revisions

From MozillaWiki
< Platform‎ | GFX‎ | WebGL
Jump to navigation Jump to search
mNo edit summary
 
(27 intermediate revisions by 2 users not shown)
Line 1: Line 1:
''(Adapted from {{bug|728354}})''
[https://bugzilla.mozilla.org/buglist.cgi?classification=Components;status_whiteboard_type=allwordssubstr;query_format=advanced;status_whiteboard=webgl-extension;bug_status=UNCONFIRMED;bug_status=NEW;bug_status=ASSIGNED;bug_status=REOPENED;product=Core Here is a Bugzilla search] returning open WebGL extension implementation 'bugs' i.e. extensions that need implementing.


Tracking bug for WebGL extension implementation is {{bug|728319}}. Check its 'Depends on' list for a list of the bugs for the various extensions.
Implementable WebGL extension specifications are found at the [http://www.khronos.org/registry/webgl/extensions/ Khronos WebGL Extension Registry].


Extension drafts for WebGL are found at the [http://www.khronos.org/registry/webgl/extensions/ Khronos WebGL Extension Registry].
==General Approach==
 
For the purposes of this page, we will pretend there is a WebGL extension named <code>WEBGL_foo_bar</code> that we're trying to implement. This extension will be listed in the [http://www.khronos.org/registry/webgl/extensions/ WebGL Extension Registry], which will link to the specification of this extension. [http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_atc/ Here's an example] of an extension specification.


Good models for how to add support for new WebGL extensions are: {{bug|684853}} and {{bug|728354}}
===Adding the Web IDL===


==General Approach==
Files to be modified in this section:
* {{moz-central|dom/webidl/WebGLRenderingContext.webidl}}
* {{moz-central|dom/bindings/Bindings.conf}}


For the purposes of this page, we will pretend there is a WebGL extension named <code>WEBGL_foo_bar</code> that we're trying to implement.
[http://www.w3.org/TR/WebIDL/ WebIDL] stands for "Web interface definition language". It's how Web APIs are specified. The extension spec should provide a snippet of WebIDL. In most cases, it can be used as-is or with very little modification in Mozilla's IDL system.


===Adding the IDL===
Add the Web IDL from the extension spec to {{moz-central|dom/webidl/WebGLRenderingContext.webidl}}. For the interface name, instead of the one given in the extension spec, try to choose a name more in line with existing interface names here. For example, for WEBGL_foo_bar, you could choose WebGLExtensionFooBar. Do not use any prefix (like MOZ_ or EXT_). Prefixes are only wanted in the extension string (see below). Here like in other places where all WebGL extensions are listed, '''please preserve alphabetic order'''. On the line just before your interface declaration, make sure that you have <code>[NoInterfaceObject]</code>. The IDL that you add should look like this:
Add the IDL from the spec to {{moz-central|dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl}}, with a new UUID.


Let's call this interface, <code>nsIWebGLExtensionFooBar</code>. A C++ header will be auto-generated from that IDL, and will define a <code>nsIWebGLExtensionFooBar</code> class. But that's just a base class. Below we'll manually define a <code>WebGLExtensionFooBar</code> (notice: no nsI prefix) class, inheriting <code>nsIWebGLExtensionFooBar</code>.
[NoInterfaceObject]
interface WebGLExtensionFooBar
{
  // maybe something here
};


===The Goop===
Add an entry about your new interface to {{moz-central|dom/bindings/Bindings.conf}}. Check existing WebGLExtension* entries for examples. You should have something like:


Edit these files, add goop similar to what there is for <code>WebGLExtensionStandardDerivatives</code> / <code>nsIWebGLExtensionStandardDerivatives</code>:
'WebGLExtensionFooBar': {
    'nativeType': 'mozilla::WebGLExtensionFooBar',
    'headerFile': 'WebGLExtensions.h'
},


*{{moz-central|dom/base/nsDOMClassInfo.cpp}}
If you need more information, consult [https://developer.mozilla.org/en-US/docs/Mozilla/WebIDL_bindings WebIDL bindings] or ask for help on IRC in channel #content
*{{moz-central|dom/base/nsDOMClassInfoClasses.h}}
*{{moz-central|js/src/xpconnect/src/dom_quickstubs.qsconf}}


===The Extension Class===
===The Extension Class===
Edit {{moz-central|content/canvas/src/WebGLExtensions.h}} and define the <code>WebGLExtensionFooBar</code> class, inheriting <code>nsIWebGLExtensionFooBar</code>, similar to what's being done for <code>WebGLExtensionStandardDerivatives</code>.


You shouldn't have to do anything nontrivial there, as this class only has to expose the constants that were already defined in the IDL, so it's already inheriting them. I would implement the (empty) constructor and destructor inline there, to save the hassle of having to add a new .cpp file just for them.
File to be '''created''' in this section:
* {{moz-central|content/canvas/src/WebGLExtensionFooBar.cpp}}
Files to be modified in this section:
* {{moz-central|content/canvas/src/WebGLExtensions.h}}
* {{moz-central|content/canvas/src/Makefile.in}}
 
Edit {{moz-central|content/canvas/src/WebGLExtensions.h}} and define the <code>WebGLExtensionFooBar</code> class, similar to what's being done for <code>WebGLExtensionStandardDerivatives</code>.
 
Create a new implementation file for your extension, say {{moz-central|content/canvas/src/WebGLExtensionFooBar.cpp}}, mimicking existing extension implementation files such as {{moz-central|content/canvas/src/WebGLExtensionStandardDerivatives.cpp}}. Add it to the list of source files in {{moz-central|content/canvas/src/Makefile.in}}.
 
This C++ class won't automatically be aware of what you've put in the IDL. If the IDL interface for this extension has methods or attributes (the majority are empty or only have constants, which don't require any C++ work), you will need to manually declare and implement the corresponding C++ methods here. See <code>WebGLExtensionLoseContext</code> for an example. For general documentation about that, refer to [https://developer.mozilla.org/en-US/docs/Mozilla/WebIDL_bindings WebIDL bindings].


===Exposing the Extension===
===Exposing the Extension===
Now let's do the work to actually expose this extension, in WebGL <code>getExtension</code> and <code>getSupportedExtensions</code> methods.
 
The file to edit is {{moz-central|content/canvas/src/WebGLContext.cpp}}
Files to be modified in this section:
* {{moz-central|content/canvas/src/WebGLContext.cpp}}
* {{moz-central|content/canvas/src/WebGLContext.h}}
These files may also have to be modified:
* {{moz-central|gfx/gl/GLContext.h}}
* {{moz-central|gfx/gl/GLContext.cpp}}
 
In this section, we do the work to actually expose this extension, in WebGL <code>getExtension</code> and <code>getSupportedExtensions</code> methods.
The file to edit is {{moz-central|content/canvas/src/WebGLContext.cpp}}. This is where you expose the extension, possibly with a MOZ_ prefix.
 
The rule to determine whether to use a <code>MOZ_</code> prefix is very simple: if the WebGL extension is a "Draft" (that's written in the spec, and in the extension registry) then you must expose it with a <code>MOZ_</code> prefix. If it is ''not'' a "Draft", then you must ''not'' expose it with a <code>MOZ_</code> prefix.
 
You will also need to add an enum value in WebGLExtensionID in {{moz-central|content/canvas/src/WebGLContext.h}}.


The functions exposed to scripts are <code>WebGLContext::GetExtension</code> and <code>WebGLContext::GetSupportedExtensions</code>. They call another internal function that you'll have to edit as well: <code>WebGLContext::IsExtensionSupported</code>. That's where you'll have to decide whether this extension is supported or not by the client. If you have to query the <code>GL_EXTENSIONS</code> string of the underlying OpenGL context, call <code>gl->IsExtensionSupported(enum value)</code>. Indeed, we are checking for a list of extensions when we create a OpenGL context, so that subsequent checking for them is really fast. If the OpenGL extensions you need to check for haven't yet been added to the list that we check for, you'll have to edit these files in a straightforward way (search for <code>IsExtensionSupported</code>):
The functions exposed to scripts are <code>WebGLContext::GetExtension</code> and <code>WebGLContext::GetSupportedExtensions</code>. They call another internal function that you'll have to edit as well: <code>WebGLContext::IsExtensionSupported</code>. That's where you'll have to decide whether this extension is supported or not by the client. If you have to query the <code>GL_EXTENSIONS</code> string of the underlying OpenGL context, call <code>gl->IsExtensionSupported(enum value)</code>. Indeed, we are checking for a list of extensions when we create a OpenGL context, so that subsequent checking for them is really fast. If the OpenGL extensions you need to check for haven't yet been added to the list that we check for, you'll have to edit these files in a straightforward way (search for <code>IsExtensionSupported</code>):
* {{moz-central|gfx/gl/GLContext.h}}
* {{moz-central|gfx/gl/GLContext.cpp}}


*{{moz-central|gfx/gl/GLContext.h}}
===Implementing the Extension===
*{{moz-central|gfx/gl/GLContext.cpp}}
Files that may typically have to be modified in this section (this depends on the extension):
* {{moz-central|content/canvas/src/WebGLContextGL.cpp}}
* {{moz-central|content/canvas/src/WebGLContextGLValidate.cpp}}
* {{moz-central|gfx/gl/GLDefs.h}}
* Any of the above .cpp or .h files


===Implementing the Extension===
Finally, let's implement what this extension actually does. The spec describes that.
Finally, let's implement what this extension actually does. The spec describes that.
The file you have to edit to do that, is {{moz-central|content/canvas/src/WebGLContextGL.cpp}}, though you might also need to make some more edits to <code>GLContext</code>, or elsewhere in <code>WebGLContext</code>.


Sometimes, what this extension does is modify the behavior of some existing methods, it should be straightforward to see what to do there. The only thing is that you'll need to use these new symbolic constants, like <code>TEXTURE_MAX_ANISOTROPY</code>. Rather than trying to use the constants from the extension class, add #defines for them in {{moz-central|gfx/gl/GLDefs.h}}.
If the extension modifies the behavior of one of the standard WebGL context methods, you will probably have to modify {{moz-central|content/canvas/src/WebGLContextGL.cpp}} as that is where these methods are implemented. You might also need to make some more edits to {{moz-central|content/canvas/src/WebGLContextGLValidate.cpp}}, or to other files in this directory, or to <code>gfx/gl/GLContext.*</code>.
(Notice we use <code>LOCAL_GL_</code> prefixes there to avoid some conflicts)
 
Sometimes, while implementing a WebGL extension, you need a new GL symbolic constant, like <code>TEXTURE_MAX_ANISOTROPY</code>. To achieve this, add #defines for them in {{moz-central|gfx/gl/GLDefs.h}}. Notice we use <code>LOCAL_GL_</code> prefixes there to avoid some conflicts.


===Adding Tests===
===Adding Tests===
Unfortunately, odds are fairly high that we don't have a test case for this particular extension! It would be very useful to write one, and even more useful to write one that can be added to the conformance test suite.  
Unfortunately, odds are fairly high that we don't have a test case for this particular extension! It would be very useful to write one, and even more useful to write one that can be added to the conformance test suite.


==Other Remarks==
==Other Remarks==
Line 52: Line 86:
*General info about getting started with Gfx hacking: [[Platform/GFX/Contribute]]
*General info about getting started with Gfx hacking: [[Platform/GFX/Contribute]]


*[http://mxr.mozilla.org/mozilla-central/ MXR] and [http://dxr.mozilla.org/mozilla/ DXR] are useful code search tools.
*[http://mxr.mozilla.org/mozilla-central/ MXR] and [http://dxr.mozilla.org DXR] are useful code search tools.


*Test your code by running the [https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/tests/webgl-conformance-tests.html WebGL conformance test suite]. (compare to a test run without your patch)
*Test your code by running the [https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/tests/webgl-conformance-tests.html WebGL conformance test suite]. (compare to a test run without your patch)
*:Or as a mozilla mochitest: (assuming that you are in your mozilla-central directory, and that obj-firefox-debug is your object directory)
*:Or as a mozilla mochitest: (assuming that you are in your mozilla-central directory, and that obj-firefox-debug is your object directory)
*::<code>TEST_PATH=content/canvas/test/webgl/test_webgl_conformance_test_suite.html make -C obj-firefox-debug/ mochitest-plain</code>
*::<code>TEST_PATH=content/canvas/test/webgl/test_webgl_conformance_test_suite.html make -C obj-firefox-debug/ mochitest-plain</code>

Latest revision as of 19:10, 11 October 2012

Here is a Bugzilla search returning open WebGL extension implementation 'bugs' i.e. extensions that need implementing.

Implementable WebGL extension specifications are found at the Khronos WebGL Extension Registry.

General Approach

For the purposes of this page, we will pretend there is a WebGL extension named WEBGL_foo_bar that we're trying to implement. This extension will be listed in the WebGL Extension Registry, which will link to the specification of this extension. Here's an example of an extension specification.

Adding the Web IDL

Files to be modified in this section:

WebIDL stands for "Web interface definition language". It's how Web APIs are specified. The extension spec should provide a snippet of WebIDL. In most cases, it can be used as-is or with very little modification in Mozilla's IDL system.

Add the Web IDL from the extension spec to mozilla-central/dom/webidl/WebGLRenderingContext.webidl. For the interface name, instead of the one given in the extension spec, try to choose a name more in line with existing interface names here. For example, for WEBGL_foo_bar, you could choose WebGLExtensionFooBar. Do not use any prefix (like MOZ_ or EXT_). Prefixes are only wanted in the extension string (see below). Here like in other places where all WebGL extensions are listed, please preserve alphabetic order. On the line just before your interface declaration, make sure that you have [NoInterfaceObject]. The IDL that you add should look like this:

[NoInterfaceObject]
interface WebGLExtensionFooBar
{
  // maybe something here
};

Add an entry about your new interface to mozilla-central/dom/bindings/Bindings.conf. Check existing WebGLExtension* entries for examples. You should have something like:

'WebGLExtensionFooBar': {
   'nativeType': 'mozilla::WebGLExtensionFooBar',
   'headerFile': 'WebGLExtensions.h'
},

If you need more information, consult WebIDL bindings or ask for help on IRC in channel #content

The Extension Class

File to be created in this section:

Files to be modified in this section:

Edit mozilla-central/content/canvas/src/WebGLExtensions.h and define the WebGLExtensionFooBar class, similar to what's being done for WebGLExtensionStandardDerivatives.

Create a new implementation file for your extension, say mozilla-central/content/canvas/src/WebGLExtensionFooBar.cpp, mimicking existing extension implementation files such as mozilla-central/content/canvas/src/WebGLExtensionStandardDerivatives.cpp. Add it to the list of source files in mozilla-central/content/canvas/src/Makefile.in.

This C++ class won't automatically be aware of what you've put in the IDL. If the IDL interface for this extension has methods or attributes (the majority are empty or only have constants, which don't require any C++ work), you will need to manually declare and implement the corresponding C++ methods here. See WebGLExtensionLoseContext for an example. For general documentation about that, refer to WebIDL bindings.

Exposing the Extension

Files to be modified in this section:

These files may also have to be modified:

In this section, we do the work to actually expose this extension, in WebGL getExtension and getSupportedExtensions methods. The file to edit is mozilla-central/content/canvas/src/WebGLContext.cpp. This is where you expose the extension, possibly with a MOZ_ prefix.

The rule to determine whether to use a MOZ_ prefix is very simple: if the WebGL extension is a "Draft" (that's written in the spec, and in the extension registry) then you must expose it with a MOZ_ prefix. If it is not a "Draft", then you must not expose it with a MOZ_ prefix.

You will also need to add an enum value in WebGLExtensionID in mozilla-central/content/canvas/src/WebGLContext.h.

The functions exposed to scripts are WebGLContext::GetExtension and WebGLContext::GetSupportedExtensions. They call another internal function that you'll have to edit as well: WebGLContext::IsExtensionSupported. That's where you'll have to decide whether this extension is supported or not by the client. If you have to query the GL_EXTENSIONS string of the underlying OpenGL context, call gl->IsExtensionSupported(enum value). Indeed, we are checking for a list of extensions when we create a OpenGL context, so that subsequent checking for them is really fast. If the OpenGL extensions you need to check for haven't yet been added to the list that we check for, you'll have to edit these files in a straightforward way (search for IsExtensionSupported):

Implementing the Extension

Files that may typically have to be modified in this section (this depends on the extension):

Finally, let's implement what this extension actually does. The spec describes that.

If the extension modifies the behavior of one of the standard WebGL context methods, you will probably have to modify mozilla-central/content/canvas/src/WebGLContextGL.cpp as that is where these methods are implemented. You might also need to make some more edits to mozilla-central/content/canvas/src/WebGLContextGLValidate.cpp, or to other files in this directory, or to gfx/gl/GLContext.*.

Sometimes, while implementing a WebGL extension, you need a new GL symbolic constant, like TEXTURE_MAX_ANISOTROPY. To achieve this, add #defines for them in mozilla-central/gfx/gl/GLDefs.h. Notice we use LOCAL_GL_ prefixes there to avoid some conflicts.

Adding Tests

Unfortunately, odds are fairly high that we don't have a test case for this particular extension! It would be very useful to write one, and even more useful to write one that can be added to the conformance test suite.

Other Remarks

  • MXR and DXR are useful code search tools.
  • Test your code by running the WebGL conformance test suite. (compare to a test run without your patch)
    Or as a mozilla mochitest: (assuming that you are in your mozilla-central directory, and that obj-firefox-debug is your object directory)
    TEST_PATH=content/canvas/test/webgl/test_webgl_conformance_test_suite.html make -C obj-firefox-debug/ mochitest-plain