|
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
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/. */ |
|
5 |
|
6 #include "TextureImageCGL.h" |
|
7 #include "GLContext.h" |
|
8 #include "gfx2DGlue.h" |
|
9 #include "gfxQuartzSurface.h" |
|
10 #include "gfxPlatform.h" |
|
11 #include "gfxFailure.h" |
|
12 |
|
13 namespace mozilla { |
|
14 |
|
15 using namespace gfx; |
|
16 |
|
17 namespace gl { |
|
18 |
|
19 TextureImageCGL::TextureImageCGL(GLuint aTexture, |
|
20 const nsIntSize& aSize, |
|
21 GLenum aWrapMode, |
|
22 ContentType aContentType, |
|
23 GLContext* aContext, |
|
24 TextureImage::Flags aFlags, |
|
25 TextureImage::ImageFormat aImageFormat) |
|
26 : BasicTextureImage(aTexture, aSize, aWrapMode, aContentType, |
|
27 aContext, aFlags, aImageFormat) |
|
28 , mPixelBuffer(0) |
|
29 , mPixelBufferSize(0) |
|
30 , mBoundPixelBuffer(false) |
|
31 {} |
|
32 |
|
33 TextureImageCGL::~TextureImageCGL() |
|
34 { |
|
35 if (mPixelBuffer) { |
|
36 mGLContext->MakeCurrent(); |
|
37 mGLContext->fDeleteBuffers(1, &mPixelBuffer); |
|
38 } |
|
39 } |
|
40 |
|
41 already_AddRefed<gfxASurface> |
|
42 TextureImageCGL::GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt) |
|
43 { |
|
44 IntSize size(aSize.width + 1, aSize.height + 1); |
|
45 mGLContext->MakeCurrent(); |
|
46 if (!mGLContext-> |
|
47 IsExtensionSupported(GLContext::ARB_pixel_buffer_object)) |
|
48 { |
|
49 return gfxPlatform::GetPlatform()-> |
|
50 CreateOffscreenSurface(size, |
|
51 gfxASurface::ContentFromFormat(aFmt)); |
|
52 } |
|
53 |
|
54 if (!mPixelBuffer) { |
|
55 mGLContext->fGenBuffers(1, &mPixelBuffer); |
|
56 } |
|
57 mGLContext->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, mPixelBuffer); |
|
58 int32_t length = size.width * 4 * size.height; |
|
59 |
|
60 if (length > mPixelBufferSize) { |
|
61 mGLContext->fBufferData(LOCAL_GL_PIXEL_UNPACK_BUFFER, length, |
|
62 NULL, LOCAL_GL_STREAM_DRAW); |
|
63 mPixelBufferSize = length; |
|
64 } |
|
65 unsigned char* data = |
|
66 (unsigned char*)mGLContext-> |
|
67 fMapBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, |
|
68 LOCAL_GL_WRITE_ONLY); |
|
69 |
|
70 mGLContext->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0); |
|
71 |
|
72 if (!data) { |
|
73 nsAutoCString failure; |
|
74 failure += "Pixel buffer binding failed: "; |
|
75 failure.AppendPrintf("%dx%d\n", size.width, size.height); |
|
76 gfx::LogFailure(failure); |
|
77 |
|
78 mGLContext->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0); |
|
79 return gfxPlatform::GetPlatform()-> |
|
80 CreateOffscreenSurface(size, |
|
81 gfxASurface::ContentFromFormat(aFmt)); |
|
82 } |
|
83 |
|
84 nsRefPtr<gfxQuartzSurface> surf = |
|
85 new gfxQuartzSurface(data, ThebesIntSize(size), size.width * 4, aFmt); |
|
86 |
|
87 mBoundPixelBuffer = true; |
|
88 return surf.forget(); |
|
89 } |
|
90 |
|
91 bool |
|
92 TextureImageCGL::FinishedSurfaceUpdate() |
|
93 { |
|
94 if (mBoundPixelBuffer) { |
|
95 mGLContext->MakeCurrent(); |
|
96 mGLContext->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, mPixelBuffer); |
|
97 mGLContext->fUnmapBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER); |
|
98 return true; |
|
99 } |
|
100 return false; |
|
101 } |
|
102 |
|
103 void |
|
104 TextureImageCGL::FinishedSurfaceUpload() |
|
105 { |
|
106 if (mBoundPixelBuffer) { |
|
107 mGLContext->MakeCurrent(); |
|
108 mGLContext->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0); |
|
109 mBoundPixelBuffer = false; |
|
110 } |
|
111 } |
|
112 |
|
113 already_AddRefed<TextureImage> |
|
114 CreateTextureImageCGL(GLContext* gl, |
|
115 const gfx::IntSize& aSize, |
|
116 TextureImage::ContentType aContentType, |
|
117 GLenum aWrapMode, |
|
118 TextureImage::Flags aFlags, |
|
119 TextureImage::ImageFormat aImageFormat) |
|
120 { |
|
121 if (!gl->IsOffscreenSizeAllowed(aSize) && |
|
122 gfxPlatform::OffMainThreadCompositingEnabled()) { |
|
123 NS_ASSERTION(aWrapMode == LOCAL_GL_CLAMP_TO_EDGE, "Can't support wrapping with tiles!"); |
|
124 nsRefPtr<TextureImage> t = new gl::TiledTextureImage(gl, aSize, aContentType, |
|
125 aFlags, aImageFormat); |
|
126 return t.forget(); |
|
127 } |
|
128 |
|
129 return CreateBasicTextureImage(gl, aSize, aContentType, aWrapMode, |
|
130 aFlags, aImageFormat); |
|
131 } |
|
132 |
|
133 already_AddRefed<TextureImage> |
|
134 TileGenFuncCGL(GLContext *gl, |
|
135 const nsIntSize& aSize, |
|
136 TextureImage::ContentType aContentType, |
|
137 TextureImage::Flags aFlags, |
|
138 TextureImage::ImageFormat aImageFormat) |
|
139 { |
|
140 bool useNearestFilter = aFlags & TextureImage::UseNearestFilter; |
|
141 gl->MakeCurrent(); |
|
142 |
|
143 GLuint texture; |
|
144 gl->fGenTextures(1, &texture); |
|
145 |
|
146 gl->fActiveTexture(LOCAL_GL_TEXTURE0); |
|
147 gl->fBindTexture(LOCAL_GL_TEXTURE_2D, texture); |
|
148 |
|
149 GLint texfilter = useNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR; |
|
150 gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter); |
|
151 gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter); |
|
152 gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); |
|
153 gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); |
|
154 |
|
155 nsRefPtr<TextureImageCGL> teximage |
|
156 (new TextureImageCGL(texture, aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, |
|
157 gl, aFlags, aImageFormat)); |
|
158 return teximage.forget(); |
|
159 } |
|
160 |
|
161 } |
|
162 } |