1 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "GLTextureImage.h"
8 #include "gfxContext.h"
9 #include "gfxPlatform.h"
11 #include "gfx2DGlue.h"
12 #include "mozilla/gfx/2D.h"
13 #include "ScopedGLHelpers.h"
14 #include "GLUploadHelpers.h"
16 #include "TextureImageEGL.h"
18 #include "TextureImageCGL.h"
21 using namespace mozilla::gfx
;
26 already_AddRefed
<TextureImage
>
27 CreateTextureImage(GLContext
* gl
,
28 const gfx::IntSize
& aSize
,
29 TextureImage::ContentType aContentType
,
31 TextureImage::Flags aFlags
,
32 TextureImage::ImageFormat aImageFormat
)
34 switch (gl
->GetContextType()) {
36 case GLContextType::CGL
:
37 return CreateTextureImageCGL(gl
, aSize
, aContentType
, aWrapMode
, aFlags
, aImageFormat
);
39 case GLContextType::EGL
:
40 return CreateTextureImageEGL(gl
, aSize
, aContentType
, aWrapMode
, aFlags
, aImageFormat
);
42 return CreateBasicTextureImage(gl
, aSize
, aContentType
, aWrapMode
, aFlags
, aImageFormat
);
47 static already_AddRefed
<TextureImage
>
48 TileGenFunc(GLContext
* gl
,
49 const nsIntSize
& aSize
,
50 TextureImage::ContentType aContentType
,
51 TextureImage::Flags aFlags
,
52 TextureImage::ImageFormat aImageFormat
)
54 switch (gl
->GetContextType()) {
56 case GLContextType::CGL
:
57 return TileGenFuncCGL(gl
, aSize
, aContentType
, aFlags
, aImageFormat
);
59 case GLContextType::EGL
:
60 return TileGenFuncEGL(gl
, aSize
, aContentType
, aFlags
, aImageFormat
);
66 already_AddRefed
<TextureImage
>
67 TextureImage::Create(GLContext
* gl
,
68 const gfx::IntSize
& size
,
69 TextureImage::ContentType contentType
,
71 TextureImage::Flags flags
)
73 return CreateTextureImage(gl
, size
, contentType
, wrapMode
, flags
);
77 TextureImage::UpdateFromDataSource(gfx::DataSourceSurface
*aSurface
,
78 const nsIntRegion
* aDestRegion
,
79 const gfx::IntPoint
* aSrcPoint
)
81 nsIntRegion destRegion
= aDestRegion
? *aDestRegion
83 aSurface
->GetSize().width
,
84 aSurface
->GetSize().height
);
85 gfx::IntPoint srcPoint
= aSrcPoint
? *aSrcPoint
86 : gfx::IntPoint(0, 0);
87 return DirectUpdate(aSurface
, destRegion
, srcPoint
);
90 gfx::IntRect
TextureImage::GetTileRect() {
91 return gfx::IntRect(gfx::IntPoint(0,0), mSize
);
94 gfx::IntRect
TextureImage::GetSrcTileRect() {
98 BasicTextureImage::~BasicTextureImage()
100 GLContext
*ctx
= mGLContext
;
101 if (ctx
->IsDestroyed() || !ctx
->IsOwningThreadCurrent()) {
102 ctx
= ctx
->GetSharedContext();
105 // If we have a context, then we need to delete the texture;
106 // if we don't have a context (either real or shared),
107 // then they went away when the contex was deleted, because it
108 // was the only one that had access to it.
109 if (ctx
&& ctx
->MakeCurrent()) {
110 ctx
->fDeleteTextures(1, &mTexture
);
115 BasicTextureImage::BeginUpdate(nsIntRegion
& aRegion
)
117 NS_ASSERTION(!mUpdateDrawTarget
, "BeginUpdate() without EndUpdate()?");
119 // determine the region the client will need to repaint
120 if (CanUploadSubTextures(mGLContext
)) {
121 GetUpdateRegion(aRegion
);
123 aRegion
= nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize
));
126 mUpdateRegion
= aRegion
;
128 nsIntRect rgnSize
= mUpdateRegion
.GetBounds();
129 if (!nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize
)).Contains(rgnSize
)) {
130 NS_ERROR("update outside of image");
134 gfx::SurfaceFormat format
=
135 (GetContentType() == gfxContentType::COLOR
) ?
136 gfx::SurfaceFormat::B8G8R8X8
: gfx::SurfaceFormat::B8G8R8A8
;
138 GetDrawTargetForUpdate(gfx::IntSize(rgnSize
.width
, rgnSize
.height
), format
);
140 return mUpdateDrawTarget
;
144 BasicTextureImage::GetUpdateRegion(nsIntRegion
& aForRegion
)
146 // if the texture hasn't been initialized yet, or something important
147 // changed, we need to recreate our backing surface and force the
148 // client to paint everything
149 if (mTextureState
!= Valid
)
150 aForRegion
= nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize
));
154 BasicTextureImage::EndUpdate()
156 NS_ASSERTION(!!mUpdateDrawTarget
, "EndUpdate() without BeginUpdate()?");
158 // FIXME: this is the slow boat. Make me fast (with GLXPixmap?).
160 RefPtr
<gfx::SourceSurface
> updateSnapshot
= mUpdateDrawTarget
->Snapshot();
161 RefPtr
<gfx::DataSourceSurface
> updateData
= updateSnapshot
->GetDataSurface();
163 bool relative
= FinishedSurfaceUpdate();
166 UploadSurfaceToTexture(mGLContext
,
170 mTextureState
== Created
,
173 FinishedSurfaceUpload();
175 mUpdateDrawTarget
= nullptr;
176 mTextureState
= Valid
;
180 BasicTextureImage::BindTexture(GLenum aTextureUnit
)
182 mGLContext
->fActiveTexture(aTextureUnit
);
183 mGLContext
->fBindTexture(LOCAL_GL_TEXTURE_2D
, mTexture
);
184 mGLContext
->fActiveTexture(LOCAL_GL_TEXTURE0
);
187 TemporaryRef
<gfx::DrawTarget
>
188 BasicTextureImage::GetDrawTargetForUpdate(const gfx::IntSize
& aSize
, gfx::SurfaceFormat aFmt
)
190 return gfx::Factory::CreateDrawTarget(gfx::BackendType::CAIRO
, aSize
, aFmt
);
194 BasicTextureImage::FinishedSurfaceUpdate()
200 BasicTextureImage::FinishedSurfaceUpload()
205 BasicTextureImage::DirectUpdate(gfx::DataSourceSurface
* aSurf
, const nsIntRegion
& aRegion
, const gfx::IntPoint
& aFrom
/* = gfx::IntPoint(0, 0) */)
207 nsIntRect bounds
= aRegion
.GetBounds();
209 if (mTextureState
!= Valid
) {
210 bounds
= nsIntRect(0, 0, mSize
.width
, mSize
.height
);
211 region
= nsIntRegion(bounds
);
217 UploadSurfaceToTexture(mGLContext
,
221 mTextureState
== Created
,
222 bounds
.TopLeft() + nsIntPoint(aFrom
.x
, aFrom
.y
),
224 mTextureState
= Valid
;
229 BasicTextureImage::Resize(const gfx::IntSize
& aSize
)
231 NS_ASSERTION(!mUpdateDrawTarget
, "Resize() while in update?");
233 mGLContext
->fBindTexture(LOCAL_GL_TEXTURE_2D
, mTexture
);
235 // This matches the logic in UploadImageDataToTexture so that
236 // we avoid mixing formats.
239 if (mGLContext
->GetPreferredARGB32Format() == LOCAL_GL_BGRA
) {
240 MOZ_ASSERT(!mGLContext
->IsGLES());
241 format
= LOCAL_GL_BGRA
;
242 type
= LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV
;
244 format
= LOCAL_GL_RGBA
;
245 type
= LOCAL_GL_UNSIGNED_BYTE
;
248 mGLContext
->fTexImage2D(LOCAL_GL_TEXTURE_2D
,
258 mTextureState
= Allocated
;
262 gfx::IntSize
TextureImage::GetSize() const {
266 TextureImage::TextureImage(const gfx::IntSize
& aSize
,
267 GLenum aWrapMode
, ContentType aContentType
,
270 , mWrapMode(aWrapMode
)
271 , mContentType(aContentType
)
272 , mFilter(GraphicsFilter::FILTER_GOOD
)
276 BasicTextureImage::BasicTextureImage(GLuint aTexture
,
277 const nsIntSize
& aSize
,
279 ContentType aContentType
,
281 TextureImage::Flags aFlags
/* = TextureImage::NoFlags */,
282 TextureImage::ImageFormat aImageFormat
/* = gfxImageFormat::Unknown */)
283 : TextureImage(aSize
, aWrapMode
, aContentType
, aFlags
, aImageFormat
)
285 , mTextureState(Created
)
286 , mGLContext(aContext
)
287 , mUpdateOffset(0, 0)
291 BasicTextureImage::BasicTextureImage(GLuint aTexture
,
292 const gfx::IntSize
& aSize
,
294 ContentType aContentType
,
296 TextureImage::Flags aFlags
,
297 TextureImage::ImageFormat aImageFormat
)
298 : TextureImage(ThebesIntSize(aSize
), aWrapMode
, aContentType
, aFlags
, aImageFormat
)
300 , mTextureState(Created
)
301 , mGLContext(aContext
)
302 , mUpdateOffset(0, 0)
306 WantsSmallTiles(GLContext
* gl
)
308 // We must use small tiles for good performance if we can't use
309 // glTexSubImage2D() for some reason.
310 if (!CanUploadSubTextures(gl
))
313 // We can't use small tiles on the SGX 540, because of races in texture upload.
314 if (gl
->WorkAroundDriverBugs() &&
315 gl
->Renderer() == GLRenderer::SGX540
)
318 // Don't use small tiles otherwise. (If we implement incremental texture upload,
319 // then we will want to revisit this.)
323 TiledTextureImage::TiledTextureImage(GLContext
* aGL
,
325 TextureImage::ContentType aContentType
,
326 TextureImage::Flags aFlags
,
327 TextureImage::ImageFormat aImageFormat
)
328 : TextureImage(aSize
, LOCAL_GL_CLAMP_TO_EDGE
, aContentType
, aFlags
)
330 , mIterationCallback(nullptr)
335 , mTextureState(Created
)
336 , mImageFormat(aImageFormat
)
338 if (!(aFlags
& TextureImage::DisallowBigImage
) && WantsSmallTiles(mGL
)) {
341 mGL
->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE
, (GLint
*) &mTileSize
);
343 if (aSize
.width
!= 0 && aSize
.height
!= 0) {
348 TiledTextureImage::~TiledTextureImage()
353 TiledTextureImage::DirectUpdate(gfx::DataSourceSurface
* aSurf
, const nsIntRegion
& aRegion
, const gfx::IntPoint
& aFrom
/* = gfx::IntPoint(0, 0) */)
355 if (mSize
.width
== 0 || mSize
.height
== 0) {
361 if (mTextureState
!= Valid
) {
362 nsIntRect bounds
= nsIntRect(0, 0, mSize
.width
, mSize
.height
);
363 region
= nsIntRegion(bounds
);
369 int oldCurrentImage
= mCurrentImage
;
370 BeginBigImageIteration();
372 nsIntRect tileRect
= ThebesIntRect(GetSrcTileRect());
373 int xPos
= tileRect
.x
;
374 int yPos
= tileRect
.y
;
376 nsIntRegion tileRegion
;
377 tileRegion
.And(region
, tileRect
); // intersect with tile
379 if (tileRegion
.IsEmpty())
382 if (CanUploadSubTextures(mGL
)) {
383 tileRegion
.MoveBy(-xPos
, -yPos
); // translate into tile local space
385 // If sub-textures are unsupported, expand to tile boundaries
386 tileRect
.x
= tileRect
.y
= 0;
387 tileRegion
= nsIntRegion(tileRect
);
390 result
&= mImages
[mCurrentImage
]->
391 DirectUpdate(aSurf
, tileRegion
, aFrom
+ gfx::IntPoint(xPos
, yPos
));
393 if (mCurrentImage
== mImages
.Length() - 1) {
394 // We know we're done, but we still need to ensure that the callback
395 // gets called (e.g. to update the uploaded region).
399 // Override a callback cancelling iteration if the texture wasn't valid.
400 // We need to force the update in that situation, or we may end up
401 // showing invalid/out-of-date texture data.
402 } while (NextTile() || (mTextureState
!= Valid
));
403 mCurrentImage
= oldCurrentImage
;
405 mTextureFormat
= mImages
[0]->GetTextureFormat();
406 mTextureState
= Valid
;
411 TiledTextureImage::GetUpdateRegion(nsIntRegion
& aForRegion
)
413 if (mTextureState
!= Valid
) {
414 // if the texture hasn't been initialized yet, or something important
415 // changed, we need to recreate our backing surface and force the
416 // client to paint everything
417 aForRegion
= nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize
));
421 nsIntRegion newRegion
;
423 // We need to query each texture with the region it will be drawing and
424 // set aForRegion to be the combination of all of these regions
425 for (unsigned i
= 0; i
< mImages
.Length(); i
++) {
426 int xPos
= (i
% mColumns
) * mTileSize
;
427 int yPos
= (i
/ mColumns
) * mTileSize
;
428 nsIntRect imageRect
= nsIntRect(nsIntPoint(xPos
,yPos
),
429 ThebesIntSize(mImages
[i
]->GetSize()));
431 if (aForRegion
.Intersects(imageRect
)) {
432 // Make a copy of the region
433 nsIntRegion subRegion
;
434 subRegion
.And(aForRegion
, imageRect
);
435 // Translate it into tile-space
436 subRegion
.MoveBy(-xPos
, -yPos
);
438 mImages
[i
]->GetUpdateRegion(subRegion
);
440 subRegion
.MoveBy(xPos
, yPos
);
441 // Add to the accumulated region
442 newRegion
.Or(newRegion
, subRegion
);
446 aForRegion
= newRegion
;
450 TiledTextureImage::BeginUpdate(nsIntRegion
& aRegion
)
452 NS_ASSERTION(!mInUpdate
, "nested update");
455 // Note, we don't call GetUpdateRegion here as if the updated region is
456 // fully contained in a single tile, we get to avoid iterating through
457 // the tiles again (and a little copying).
458 if (mTextureState
!= Valid
)
460 // if the texture hasn't been initialized yet, or something important
461 // changed, we need to recreate our backing surface and force the
462 // client to paint everything
463 aRegion
= nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize
));
466 nsIntRect bounds
= aRegion
.GetBounds();
468 for (unsigned i
= 0; i
< mImages
.Length(); i
++) {
469 int xPos
= (i
% mColumns
) * mTileSize
;
470 int yPos
= (i
/ mColumns
) * mTileSize
;
471 nsIntRegion imageRegion
=
472 nsIntRegion(nsIntRect(nsIntPoint(xPos
,yPos
),
473 ThebesIntSize(mImages
[i
]->GetSize())));
475 // a single Image can handle this update request
476 if (imageRegion
.Contains(aRegion
)) {
477 // adjust for tile offset
478 aRegion
.MoveBy(-xPos
, -yPos
);
479 // forward the actual call
480 RefPtr
<gfx::DrawTarget
> drawTarget
= mImages
[i
]->BeginUpdate(aRegion
);
481 // caller expects container space
482 aRegion
.MoveBy(xPos
, yPos
);
483 // we don't have a temp surface
484 mUpdateDrawTarget
= nullptr;
485 // remember which image to EndUpdate
487 return drawTarget
.get();
491 // Get the real updated region, taking into account the capabilities of
492 // each TextureImage tile
493 GetUpdateRegion(aRegion
);
494 mUpdateRegion
= aRegion
;
495 bounds
= aRegion
.GetBounds();
497 // update covers multiple Images - create a temp surface to paint in
498 gfx::SurfaceFormat format
=
499 (GetContentType() == gfxContentType::COLOR
) ?
500 gfx::SurfaceFormat::B8G8R8X8
: gfx::SurfaceFormat::B8G8R8A8
;
501 mUpdateDrawTarget
= gfx::Factory::CreateDrawTarget(gfx::BackendType::CAIRO
,
502 bounds
.Size().ToIntSize(),
505 return mUpdateDrawTarget
;;
509 TiledTextureImage::EndUpdate()
511 NS_ASSERTION(mInUpdate
, "EndUpdate not in update");
512 if (!mUpdateDrawTarget
) { // update was to a single TextureImage
513 mImages
[mCurrentImage
]->EndUpdate();
515 mTextureState
= Valid
;
516 mTextureFormat
= mImages
[mCurrentImage
]->GetTextureFormat();
520 RefPtr
<gfx::SourceSurface
> updateSnapshot
= mUpdateDrawTarget
->Snapshot();
521 RefPtr
<gfx::DataSourceSurface
> updateData
= updateSnapshot
->GetDataSurface();
523 // upload tiles from temp surface
524 for (unsigned i
= 0; i
< mImages
.Length(); i
++) {
525 int xPos
= (i
% mColumns
) * mTileSize
;
526 int yPos
= (i
/ mColumns
) * mTileSize
;
527 nsIntRect imageRect
= nsIntRect(nsIntPoint(xPos
,yPos
),
528 ThebesIntSize(mImages
[i
]->GetSize()));
530 nsIntRegion subregion
;
531 subregion
.And(mUpdateRegion
, imageRect
);
532 if (subregion
.IsEmpty())
534 subregion
.MoveBy(-xPos
, -yPos
); // Tile-local space
535 // copy tile from temp target
536 gfx::DrawTarget
* drawTarget
= mImages
[i
]->BeginUpdate(subregion
);
537 MOZ_ASSERT(drawTarget
->GetBackendType() == BackendType::CAIRO
,
538 "updateSnapshot should not have been converted to data");
539 gfxUtils::ClipToRegion(drawTarget
, subregion
);
540 Size
size(updateData
->GetSize().width
,
541 updateData
->GetSize().height
);
542 drawTarget
->DrawSurface(updateData
,
543 Rect(Point(-xPos
, -yPos
), size
),
544 Rect(Point(0, 0), size
),
545 DrawSurfaceOptions(),
546 DrawOptions(1.0, CompositionOp::OP_SOURCE
,
547 AntialiasMode::NONE
));
548 drawTarget
->PopClip();
549 mImages
[i
]->EndUpdate();
552 mUpdateDrawTarget
= nullptr;
554 mTextureFormat
= mImages
[0]->GetTextureFormat();
555 mTextureState
= Valid
;
558 void TiledTextureImage::BeginBigImageIteration()
563 bool TiledTextureImage::NextTile()
565 bool continueIteration
= true;
567 if (mIterationCallback
)
568 continueIteration
= mIterationCallback(this, mCurrentImage
,
569 mIterationCallbackData
);
571 if (mCurrentImage
+ 1 < mImages
.Length()) {
573 return continueIteration
;
578 void TiledTextureImage::SetIterationCallback(BigImageIterationCallback aCallback
,
581 mIterationCallback
= aCallback
;
582 mIterationCallbackData
= aCallbackData
;
585 gfx::IntRect
TiledTextureImage::GetTileRect()
587 if (!GetTileCount()) {
588 return gfx::IntRect();
590 gfx::IntRect rect
= mImages
[mCurrentImage
]->GetTileRect();
591 unsigned int xPos
= (mCurrentImage
% mColumns
) * mTileSize
;
592 unsigned int yPos
= (mCurrentImage
/ mColumns
) * mTileSize
;
593 rect
.MoveBy(xPos
, yPos
);
597 gfx::IntRect
TiledTextureImage::GetSrcTileRect()
599 gfx::IntRect rect
= GetTileRect();
600 const bool needsYFlip
= mFlags
& OriginBottomLeft
;
601 unsigned int srcY
= needsYFlip
? mSize
.height
- rect
.height
- rect
.y
603 return gfx::IntRect(rect
.x
, srcY
, rect
.width
, rect
.height
);
607 TiledTextureImage::BindTexture(GLenum aTextureUnit
)
609 if (!GetTileCount()) {
612 mImages
[mCurrentImage
]->BindTexture(aTextureUnit
);
616 * Resize, trying to reuse tiles. The reuse strategy is to decide on reuse per
617 * column. A tile on a column is reused if it hasn't changed size, otherwise it
618 * is discarded/replaced. Extra tiles on a column are pruned after iterating
619 * each column, and extra rows are pruned after iteration over the entire image
622 void TiledTextureImage::Resize(const gfx::IntSize
& aSize
)
624 if (mSize
== aSize
&& mTextureState
!= Created
) {
628 // calculate rows and columns, rounding up
629 unsigned int columns
= (aSize
.width
+ mTileSize
- 1) / mTileSize
;
630 unsigned int rows
= (aSize
.height
+ mTileSize
- 1) / mTileSize
;
632 // Iterate over old tile-store and insert/remove tiles as necessary
635 for (row
= 0; row
< (int)rows
; row
++) {
636 // If we've gone beyond how many rows there were before, set mColumns to
637 // zero so that we only create new tiles.
638 if (row
>= (int)mRows
)
641 // Similarly, if we're on the last row of old tiles and the height has
642 // changed, discard all tiles in that row.
643 // This will cause the pruning of columns not to work, but we don't need
644 // to worry about that, as no more tiles will be reused past this point
646 if ((row
== (int)mRows
- 1) && (aSize
.height
!= mSize
.height
))
650 for (col
= 0; col
< (int)columns
; col
++) {
651 nsIntSize
size( // use tilesize first, then the remainder
652 (col
+1) * mTileSize
> (unsigned int)aSize
.width
? aSize
.width
% mTileSize
: mTileSize
,
653 (row
+1) * mTileSize
> (unsigned int)aSize
.height
? aSize
.height
% mTileSize
: mTileSize
);
655 bool replace
= false;
657 // Check if we can re-use old tiles.
658 if (col
< (int)mColumns
) {
659 // Reuse an existing tile. If the tile is an end-tile and the
660 // width differs, replace it instead.
661 if (mSize
.width
!= aSize
.width
) {
662 if (col
== (int)mColumns
- 1) {
663 // Tile at the end of the old column, replace it with
666 } else if (col
== (int)columns
- 1) {
667 // Tile at the end of the new column, create a new one.
669 // Before the last column on both the old and new sizes,
670 // reuse existing tile.
675 // Width hasn't changed, reuse existing tile.
681 // Create a new tile.
682 nsRefPtr
<TextureImage
> teximg
=
683 TileGenFunc(mGL
, size
, mContentType
, mFlags
, mImageFormat
);
685 mImages
.ReplaceElementAt(i
, teximg
);
687 mImages
.InsertElementAt(i
, teximg
);
691 // Prune any unused tiles on the end of the column.
692 if (row
< (int)mRows
) {
693 for (col
= (int)mColumns
- col
; col
> 0; col
--) {
694 mImages
.RemoveElementAt(i
);
699 // Prune any unused tiles at the end of the store.
700 unsigned int length
= mImages
.Length();
701 for (; i
< length
; i
++)
702 mImages
.RemoveElementAt(mImages
.Length()-1);
704 // Reset tile-store properties.
708 mTextureState
= Allocated
;
712 uint32_t TiledTextureImage::GetTileCount()
714 return mImages
.Length();
717 already_AddRefed
<TextureImage
>
718 CreateBasicTextureImage(GLContext
* aGL
,
719 const gfx::IntSize
& aSize
,
720 TextureImage::ContentType aContentType
,
722 TextureImage::Flags aFlags
,
723 TextureImage::ImageFormat aImageFormat
)
725 bool useNearestFilter
= aFlags
& TextureImage::UseNearestFilter
;
726 if (!aGL
->MakeCurrent()) {
731 aGL
->fGenTextures(1, &texture
);
733 ScopedBindTexture
bind(aGL
, texture
);
735 GLint texfilter
= useNearestFilter
? LOCAL_GL_NEAREST
: LOCAL_GL_LINEAR
;
736 aGL
->fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_MIN_FILTER
, texfilter
);
737 aGL
->fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_MAG_FILTER
, texfilter
);
738 aGL
->fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_WRAP_S
, aWrapMode
);
739 aGL
->fTexParameteri(LOCAL_GL_TEXTURE_2D
, LOCAL_GL_TEXTURE_WRAP_T
, aWrapMode
);
741 nsRefPtr
<BasicTextureImage
> texImage
=
742 new BasicTextureImage(texture
, aSize
, aWrapMode
, aContentType
,
743 aGL
, aFlags
, aImageFormat
);
744 return texImage
.forget();