1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Corporation code.
16 : *
17 : * The Initial Developer of the Original Code is Mozilla Foundation.
18 : * Portions created by the Initial Developer are Copyright (C) 2009
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Bas Schouten <bschouten@mozilla.org>
23 : * Frederic Plourde <frederic.plourde@collabora.co.uk>
24 : * Vladimir Vukicevic <vladimir@pobox.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifndef GFX_LAYERMANAGEROGL_H
41 : #define GFX_LAYERMANAGEROGL_H
42 :
43 : #include "Layers.h"
44 :
45 : #include "mozilla/layers/ShadowLayers.h"
46 :
47 : #include "mozilla/TimeStamp.h"
48 :
49 : #ifdef XP_WIN
50 : #include <windows.h>
51 : #endif
52 :
53 : /**
54 : * We don't include GLDefs.h here since we don't want to drag in all defines
55 : * in for all our users.
56 : */
57 : typedef unsigned int GLenum;
58 : typedef unsigned int GLbitfield;
59 : typedef unsigned int GLuint;
60 : typedef int GLint;
61 : typedef int GLsizei;
62 :
63 : #define BUFFER_OFFSET(i) ((char *)NULL + (i))
64 :
65 : #include "gfxContext.h"
66 : #include "gfx3DMatrix.h"
67 : #include "nsIWidget.h"
68 : #include "GLContext.h"
69 :
70 : #include "LayerManagerOGLProgram.h"
71 :
72 : namespace mozilla {
73 : namespace layers {
74 :
75 : class LayerOGL;
76 : class ShadowThebesLayer;
77 : class ShadowContainerLayer;
78 : class ShadowImageLayer;
79 : class ShadowCanvasLayer;
80 : class ShadowColorLayer;
81 :
82 : /**
83 : * This is the LayerManager used for OpenGL 2.1. For now this will render on
84 : * the main thread.
85 : */
86 : class THEBES_API LayerManagerOGL :
87 : public ShadowLayerManager
88 : {
89 : typedef mozilla::gl::GLContext GLContext;
90 : typedef mozilla::gl::ShaderProgramType ProgramType;
91 :
92 : public:
93 : LayerManagerOGL(nsIWidget *aWidget);
94 : virtual ~LayerManagerOGL();
95 :
96 : void CleanupResources();
97 :
98 : void Destroy();
99 :
100 :
101 : /**
102 : * Initializes the layer manager with a given GLContext. If aContext is null
103 : * then the layer manager will try to create one for the associated widget.
104 : *
105 : * \param aContext an existing GL context to use. Can be created with CreateContext()
106 : *
107 : * \return True is initialization was succesful, false when it was not.
108 : */
109 0 : bool Initialize(bool force = false) {
110 0 : return Initialize(CreateContext(), force);
111 : }
112 :
113 : bool Initialize(nsRefPtr<GLContext> aContext, bool force = false);
114 :
115 : /**
116 : * Sets the clipping region for this layer manager. This is important on
117 : * windows because using OGL we no longer have GDI's native clipping. Therefor
118 : * widget must tell us what part of the screen is being invalidated,
119 : * and we should clip to this.
120 : *
121 : * \param aClippingRegion Region to clip to. Setting an empty region
122 : * will disable clipping.
123 : */
124 : void SetClippingRegion(const nsIntRegion& aClippingRegion);
125 :
126 : /**
127 : * LayerManager implementation.
128 : */
129 : virtual ShadowLayerManager* AsShadowManager()
130 : {
131 : return this;
132 : }
133 :
134 : void BeginTransaction();
135 :
136 : void BeginTransactionWithTarget(gfxContext* aTarget);
137 :
138 : void EndConstruction();
139 :
140 : virtual bool EndEmptyTransaction();
141 : virtual void EndTransaction(DrawThebesLayerCallback aCallback,
142 : void* aCallbackData,
143 : EndTransactionFlags aFlags = END_DEFAULT);
144 :
145 : virtual void SetRoot(Layer* aLayer) { mRoot = aLayer; }
146 :
147 : virtual bool CanUseCanvasLayerForSize(const gfxIntSize &aSize)
148 : {
149 : if (!mGLContext)
150 : return false;
151 : PRInt32 maxSize = mGLContext->GetMaxTextureSize();
152 : return aSize <= gfxIntSize(maxSize, maxSize);
153 : }
154 :
155 : virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
156 :
157 : virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
158 :
159 : virtual already_AddRefed<ImageLayer> CreateImageLayer();
160 :
161 : virtual already_AddRefed<ColorLayer> CreateColorLayer();
162 :
163 : virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
164 :
165 : virtual already_AddRefed<ShadowThebesLayer> CreateShadowThebesLayer();
166 : virtual already_AddRefed<ShadowContainerLayer> CreateShadowContainerLayer();
167 : virtual already_AddRefed<ShadowImageLayer> CreateShadowImageLayer();
168 : virtual already_AddRefed<ShadowColorLayer> CreateShadowColorLayer();
169 : virtual already_AddRefed<ShadowCanvasLayer> CreateShadowCanvasLayer();
170 :
171 : virtual LayersBackend GetBackendType() { return LAYERS_OPENGL; }
172 : virtual void GetBackendName(nsAString& name) { name.AssignLiteral("OpenGL"); }
173 :
174 : /**
175 : * Helper methods.
176 : */
177 : void MakeCurrent(bool aForce = false) {
178 : if (mDestroyed) {
179 : NS_WARNING("Call on destroyed layer manager");
180 : return;
181 : }
182 : mGLContext->MakeCurrent(aForce);
183 : }
184 :
185 : ColorTextureLayerProgram *GetColorTextureLayerProgram(ProgramType type){
186 : return static_cast<ColorTextureLayerProgram*>(mPrograms[type]);
187 : }
188 :
189 : ColorTextureLayerProgram *GetRGBALayerProgram() {
190 : return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::RGBALayerProgramType]);
191 : }
192 : ColorTextureLayerProgram *GetBGRALayerProgram() {
193 : return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::BGRALayerProgramType]);
194 : }
195 : ColorTextureLayerProgram *GetRGBXLayerProgram() {
196 : return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::RGBXLayerProgramType]);
197 : }
198 : ColorTextureLayerProgram *GetBGRXLayerProgram() {
199 : return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::BGRXLayerProgramType]);
200 : }
201 : ColorTextureLayerProgram *GetBasicLayerProgram(bool aOpaque, bool aIsRGB)
202 : {
203 : if (aIsRGB) {
204 : return aOpaque
205 : ? GetRGBXLayerProgram()
206 : : GetRGBALayerProgram();
207 : } else {
208 : return aOpaque
209 : ? GetBGRXLayerProgram()
210 : : GetBGRALayerProgram();
211 : }
212 : }
213 :
214 : ColorTextureLayerProgram *GetRGBARectLayerProgram() {
215 : return static_cast<ColorTextureLayerProgram*>(mPrograms[gl::RGBARectLayerProgramType]);
216 : }
217 : SolidColorLayerProgram *GetColorLayerProgram() {
218 : return static_cast<SolidColorLayerProgram*>(mPrograms[gl::ColorLayerProgramType]);
219 : }
220 : YCbCrTextureLayerProgram *GetYCbCrLayerProgram() {
221 : return static_cast<YCbCrTextureLayerProgram*>(mPrograms[gl::YCbCrLayerProgramType]);
222 : }
223 : ComponentAlphaTextureLayerProgram *GetComponentAlphaPass1LayerProgram() {
224 : return static_cast<ComponentAlphaTextureLayerProgram*>
225 : (mPrograms[gl::ComponentAlphaPass1ProgramType]);
226 : }
227 : ComponentAlphaTextureLayerProgram *GetComponentAlphaPass2LayerProgram() {
228 : return static_cast<ComponentAlphaTextureLayerProgram*>
229 : (mPrograms[gl::ComponentAlphaPass2ProgramType]);
230 : }
231 : CopyProgram *GetCopy2DProgram() {
232 : return static_cast<CopyProgram*>(mPrograms[gl::Copy2DProgramType]);
233 : }
234 : CopyProgram *GetCopy2DRectProgram() {
235 : return static_cast<CopyProgram*>(mPrograms[gl::Copy2DRectProgramType]);
236 : }
237 :
238 : ColorTextureLayerProgram *GetFBOLayerProgram() {
239 : return static_cast<ColorTextureLayerProgram*>(mPrograms[GetFBOLayerProgramType()]);
240 : }
241 :
242 : gl::ShaderProgramType GetFBOLayerProgramType() {
243 : if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB)
244 : return gl::RGBARectLayerProgramType;
245 : return gl::RGBALayerProgramType;
246 : }
247 :
248 0 : GLContext *gl() const { return mGLContext; }
249 :
250 : DrawThebesLayerCallback GetThebesLayerCallback() const
251 : { return mThebesLayerCallback; }
252 :
253 : void* GetThebesLayerCallbackData() const
254 : { return mThebesLayerCallbackData; }
255 :
256 : // This is a GLContext that can be used for resource
257 : // management (creation, destruction). It is guaranteed
258 : // to be either the same as the gl() context, or a context
259 : // that is in the same share pool.
260 : GLContext *glForResources() const {
261 : if (mGLContext->GetSharedContext())
262 : return mGLContext->GetSharedContext();
263 : return mGLContext;
264 : }
265 :
266 : /*
267 : * Helper functions for our layers
268 : */
269 : void CallThebesLayerDrawCallback(ThebesLayer* aLayer,
270 : gfxContext* aContext,
271 : const nsIntRegion& aRegionToDraw)
272 : {
273 : NS_ASSERTION(mThebesLayerCallback,
274 : "CallThebesLayerDrawCallback without callback!");
275 : mThebesLayerCallback(aLayer, aContext,
276 : aRegionToDraw, nsIntRegion(),
277 : mThebesLayerCallbackData);
278 : }
279 :
280 : GLenum FBOTextureTarget() { return mFBOTextureTarget; }
281 :
282 : /**
283 : * Controls how to initialize the texture / FBO created by
284 : * CreateFBOWithTexture.
285 : * - InitModeNone: No initialization, contents are undefined.
286 : * - InitModeClear: Clears the FBO.
287 : * - InitModeCopy: Copies the contents of the current glReadBuffer into the
288 : * texture.
289 : */
290 : enum InitMode {
291 : InitModeNone,
292 : InitModeClear,
293 : InitModeCopy
294 : };
295 :
296 : /* Create a FBO backed by a texture; will leave the FBO
297 : * bound. Note that the texture target type will be
298 : * of the type returned by FBOTextureTarget; different
299 : * shaders are required to sample from the different
300 : * texture types.
301 : */
302 : void CreateFBOWithTexture(const nsIntRect& aRect, InitMode aInit,
303 : GLuint aCurrentFrameBuffer,
304 : GLuint *aFBO, GLuint *aTexture);
305 :
306 : GLuint QuadVBO() { return mQuadVBO; }
307 : GLintptr QuadVBOVertexOffset() { return 0; }
308 : GLintptr QuadVBOTexCoordOffset() { return sizeof(float)*4*2; }
309 : GLintptr QuadVBOFlippedTexCoordOffset() { return sizeof(float)*8*2; }
310 :
311 : void BindQuadVBO() {
312 : mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO);
313 : }
314 :
315 : void QuadVBOVerticesAttrib(GLuint aAttribIndex) {
316 : mGLContext->fVertexAttribPointer(aAttribIndex, 2,
317 : LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
318 : (GLvoid*) QuadVBOVertexOffset());
319 : }
320 :
321 : void QuadVBOTexCoordsAttrib(GLuint aAttribIndex) {
322 : mGLContext->fVertexAttribPointer(aAttribIndex, 2,
323 : LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
324 : (GLvoid*) QuadVBOTexCoordOffset());
325 : }
326 :
327 : void QuadVBOFlippedTexCoordsAttrib(GLuint aAttribIndex) {
328 : mGLContext->fVertexAttribPointer(aAttribIndex, 2,
329 : LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
330 : (GLvoid*) QuadVBOFlippedTexCoordOffset());
331 : }
332 :
333 : // Super common
334 :
335 : void BindAndDrawQuad(GLuint aVertAttribIndex,
336 : GLuint aTexCoordAttribIndex,
337 : bool aFlipped = false)
338 : {
339 : BindQuadVBO();
340 : QuadVBOVerticesAttrib(aVertAttribIndex);
341 :
342 : if (aTexCoordAttribIndex != GLuint(-1)) {
343 : if (aFlipped)
344 : QuadVBOFlippedTexCoordsAttrib(aTexCoordAttribIndex);
345 : else
346 : QuadVBOTexCoordsAttrib(aTexCoordAttribIndex);
347 :
348 : mGLContext->fEnableVertexAttribArray(aTexCoordAttribIndex);
349 : }
350 :
351 : mGLContext->fEnableVertexAttribArray(aVertAttribIndex);
352 :
353 : mGLContext->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
354 :
355 : mGLContext->fDisableVertexAttribArray(aVertAttribIndex);
356 :
357 : if (aTexCoordAttribIndex != GLuint(-1)) {
358 : mGLContext->fDisableVertexAttribArray(aTexCoordAttribIndex);
359 : }
360 : }
361 :
362 : void BindAndDrawQuad(LayerProgram *aProg,
363 : bool aFlipped = false)
364 : {
365 : BindAndDrawQuad(aProg->AttribLocation(LayerProgram::VertexAttrib),
366 : aProg->AttribLocation(LayerProgram::TexCoordAttrib),
367 : aFlipped);
368 : }
369 :
370 : void BindAndDrawQuadWithTextureRect(LayerProgram *aProg,
371 : const nsIntRect& aTexCoordRect,
372 : const nsIntSize& aTexSize,
373 : GLenum aWrapMode = LOCAL_GL_REPEAT);
374 :
375 :
376 : #ifdef MOZ_LAYERS_HAVE_LOG
377 : virtual const char* Name() const { return "OGL"; }
378 : #endif // MOZ_LAYERS_HAVE_LOG
379 :
380 : const nsIntSize& GetWigetSize() {
381 : return mWidgetSize;
382 : }
383 :
384 : enum WorldTransforPolicy {
385 : ApplyWorldTransform,
386 : DontApplyWorldTransform
387 : };
388 :
389 : /**
390 : * Setup the viewport and projection matrix for rendering
391 : * to a window of the given dimensions.
392 : */
393 : void SetupPipeline(int aWidth, int aHeight, WorldTransforPolicy aTransformPolicy);
394 :
395 : /**
396 : * Setup World transform matrix.
397 : * Transform will be ignored if it is not PreservesAxisAlignedRectangles
398 : * or has non integer scale
399 : */
400 : void SetWorldTransform(const gfxMatrix& aMatrix);
401 : gfxMatrix& GetWorldTransform(void);
402 : void WorldTransformRect(nsIntRect& aRect);
403 :
404 : private:
405 : /** Widget associated with this layer manager */
406 : nsIWidget *mWidget;
407 : nsIntSize mWidgetSize;
408 :
409 : /**
410 : * Context target, NULL when drawing directly to our swap chain.
411 : */
412 : nsRefPtr<gfxContext> mTarget;
413 :
414 : nsRefPtr<GLContext> mGLContext;
415 :
416 : already_AddRefed<mozilla::gl::GLContext> CreateContext();
417 :
418 : static ProgramType sLayerProgramTypes[];
419 :
420 : /** Backbuffer */
421 : GLuint mBackBufferFBO;
422 : GLuint mBackBufferTexture;
423 : nsIntSize mBackBufferSize;
424 :
425 : /** Shader Programs */
426 : nsTArray<LayerManagerOGLProgram*> mPrograms;
427 :
428 : /** Texture target to use for FBOs */
429 : GLenum mFBOTextureTarget;
430 :
431 : /** VBO that has some basics in it for a textured quad,
432 : * including vertex coords and texcoords for both
433 : * flipped and unflipped textures */
434 : GLuint mQuadVBO;
435 :
436 : /** Region we're clipping our current drawing to. */
437 : nsIntRegion mClippingRegion;
438 :
439 : /** Misc */
440 : bool mHasBGRA;
441 :
442 : /** Current root layer. */
443 : LayerOGL *RootLayer() const;
444 :
445 : /**
446 : * Render the current layer tree to the active target.
447 : */
448 : void Render();
449 :
450 : /**
451 : * Setup a backbuffer of the given dimensions.
452 : */
453 : void SetupBackBuffer(int aWidth, int aHeight);
454 :
455 : /**
456 : * Copies the content of our backbuffer to the set transaction target.
457 : */
458 : void CopyToTarget(gfxContext *aTarget);
459 :
460 : /**
461 : * Updates all layer programs with a new projection matrix.
462 : *
463 : * XXX we need a way to be able to delay setting this until
464 : * the program is actually used. Maybe a DelayedSetUniform
465 : * on Program, that will delay the set until the next Activate?
466 : *
467 : * XXX this is only called once per frame, so it's not awful.
468 : * If we have any more similar updates, then we should delay.
469 : */
470 : void SetLayerProgramProjectionMatrix(const gfx3DMatrix& aMatrix);
471 :
472 : /* Thebes layer callbacks; valid at the end of a transaciton,
473 : * while rendering */
474 : DrawThebesLayerCallback mThebesLayerCallback;
475 : void *mThebesLayerCallbackData;
476 : gfxMatrix mWorldMatrix;
477 :
478 : struct FPSState
479 : {
480 : GLuint texture;
481 : int fps;
482 : bool initialized;
483 : int fcount;
484 : TimeStamp last;
485 :
486 : FPSState()
487 : : texture(0)
488 : , fps(0)
489 : , initialized(false)
490 : , fcount(0)
491 : {
492 : last = TimeStamp::Now();
493 : }
494 : void DrawFPS(GLContext*, CopyProgram*);
495 : } mFPS;
496 :
497 : static bool sDrawFPS;
498 : };
499 :
500 : /**
501 : * General information and tree management for OGL layers.
502 : */
503 : class LayerOGL
504 : {
505 : public:
506 : LayerOGL(LayerManagerOGL *aManager)
507 : : mOGLManager(aManager), mDestroyed(false)
508 : { }
509 :
510 : virtual ~LayerOGL() { }
511 :
512 : virtual LayerOGL *GetFirstChildOGL() {
513 : return nsnull;
514 : }
515 :
516 : /* Do NOT call this from the generic LayerOGL destructor. Only from the
517 : * concrete class destructor
518 : */
519 : virtual void Destroy() = 0;
520 :
521 : virtual Layer* GetLayer() = 0;
522 :
523 : virtual void RenderLayer(int aPreviousFrameBuffer,
524 : const nsIntPoint& aOffset) = 0;
525 :
526 : typedef mozilla::gl::GLContext GLContext;
527 :
528 : LayerManagerOGL* OGLManager() const { return mOGLManager; }
529 : GLContext *gl() const { return mOGLManager->gl(); }
530 : virtual void CleanupResources() = 0;
531 :
532 : protected:
533 : LayerManagerOGL *mOGLManager;
534 : bool mDestroyed;
535 : };
536 :
537 : } /* layers */
538 : } /* mozilla */
539 :
540 : #endif /* GFX_LAYERMANAGEROGL_H */
|