author | serb |
Sun, 19 May 2019 17:20:21 -0700 | |
changeset 58616 | be9ef671a1b6 |
parent 47216 | 71c04702a3d5 |
child 58626 | a9ed3d93cca3 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
58616 | 2 |
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
#ifndef HEADLESS |
|
27 |
||
28 |
#include <jni.h> |
|
29 |
#include <jlong.h> |
|
30 |
||
31 |
#include "SurfaceData.h" |
|
32 |
#include "OGLBlitLoops.h" |
|
33 |
#include "OGLRenderQueue.h" |
|
34 |
#include "OGLSurfaceData.h" |
|
35 |
#include "GraphicsPrimitiveMgr.h" |
|
36 |
||
25127 | 37 |
#include <stdlib.h> // malloc |
38 |
#include <string.h> // memcpy |
|
39 |
#include "IntArgbPre.h" |
|
40 |
||
2 | 41 |
extern OGLPixelFormat PixelFormats[]; |
42 |
||
43 |
/** |
|
44 |
* Inner loop used for copying a source OpenGL "Surface" (window, pbuffer, |
|
45 |
* etc.) to a destination OpenGL "Surface". Note that the same surface can |
|
46 |
* be used as both the source and destination, as is the case in a copyArea() |
|
47 |
* operation. This method is invoked from OGLBlitLoops_IsoBlit() as well as |
|
48 |
* OGLBlitLoops_CopyArea(). |
|
49 |
* |
|
50 |
* The standard glCopyPixels() mechanism is used to copy the source region |
|
51 |
* into the destination region. If the regions have different dimensions, |
|
52 |
* the source will be scaled into the destination as appropriate (only |
|
53 |
* nearest neighbor filtering will be applied for simple scale operations). |
|
54 |
*/ |
|
55 |
static void |
|
56 |
OGLBlitSurfaceToSurface(OGLContext *oglc, OGLSDOps *srcOps, OGLSDOps *dstOps, |
|
57 |
jint sx1, jint sy1, jint sx2, jint sy2, |
|
58 |
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2) |
|
59 |
{ |
|
60 |
GLfloat scalex, scaley; |
|
61 |
jint srcw = sx2 - sx1; |
|
62 |
jint srch = sy2 - sy1; |
|
63 |
||
64 |
scalex = ((GLfloat)(dx2-dx1)) / srcw; |
|
65 |
scaley = ((GLfloat)(dy2-dy1)) / srch; |
|
66 |
||
67 |
// the following lines account for the fact that glCopyPixels() copies a |
|
68 |
// region whose lower-left corner is at (x,y), but the source parameters |
|
69 |
// (sx1,sy1) we are given here point to the upper-left corner of the |
|
70 |
// source region... so here we play with the sy1 and dy1 parameters so |
|
71 |
// that they point to the lower-left corners of the regions... |
|
72 |
sx1 = srcOps->xOffset + sx1; |
|
73 |
sy1 = srcOps->yOffset + srcOps->height - sy2; |
|
74 |
dy1 = dy2; |
|
75 |
||
76 |
if (oglc->extraAlpha != 1.0f) { |
|
77 |
OGLContext_SetExtraAlpha(oglc->extraAlpha); |
|
78 |
} |
|
79 |
||
80 |
// see OGLBlitSwToSurface() for more info on the following two lines |
|
81 |
j2d_glRasterPos2i(0, 0); |
|
82 |
j2d_glBitmap(0, 0, 0, 0, (GLfloat)dx1, (GLfloat)-dy1, NULL); |
|
83 |
||
84 |
if (scalex == 1.0f && scaley == 1.0f) { |
|
85 |
j2d_glCopyPixels(sx1, sy1, srcw, srch, GL_COLOR); |
|
86 |
} else { |
|
87 |
j2d_glPixelZoom(scalex, scaley); |
|
88 |
j2d_glCopyPixels(sx1, sy1, srcw, srch, GL_COLOR); |
|
89 |
j2d_glPixelZoom(1.0f, 1.0f); |
|
90 |
} |
|
91 |
||
92 |
if (oglc->extraAlpha != 1.0f) { |
|
93 |
OGLContext_SetExtraAlpha(1.0f); |
|
94 |
} |
|
95 |
} |
|
96 |
||
97 |
/** |
|
98 |
* Inner loop used for copying a source OpenGL "Texture" to a destination |
|
99 |
* OpenGL "Surface". This method is invoked from OGLBlitLoops_IsoBlit(). |
|
100 |
* |
|
101 |
* This method will copy, scale, or transform the source texture into the |
|
102 |
* destination depending on the transform state, as established in |
|
103 |
* and OGLContext_SetTransform(). If the source texture is |
|
104 |
* transformed in any way when rendered into the destination, the filtering |
|
105 |
* method applied is determined by the hint parameter (can be GL_NEAREST or |
|
106 |
* GL_LINEAR). |
|
107 |
*/ |
|
108 |
static void |
|
109 |
OGLBlitTextureToSurface(OGLContext *oglc, |
|
110 |
OGLSDOps *srcOps, OGLSDOps *dstOps, |
|
111 |
jboolean rtt, jint hint, |
|
112 |
jint sx1, jint sy1, jint sx2, jint sy2, |
|
113 |
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2) |
|
114 |
{ |
|
115 |
GLdouble tx1, ty1, tx2, ty2; |
|
116 |
||
117 |
if (rtt) { |
|
118 |
/* |
|
119 |
* The source is a render-to-texture surface. These surfaces differ |
|
120 |
* from regular texture objects in that the bottom scanline (of |
|
121 |
* the actual image content) coincides with the top edge of the |
|
122 |
* texture object. Therefore, we need to adjust the sy1/sy2 |
|
123 |
* coordinates relative to the top scanline of the image content. |
|
124 |
* |
|
125 |
* In texture coordinates, the top-left corner of the image content |
|
126 |
* would be at: |
|
127 |
* (0.0, (imgHeight/texHeight)) |
|
128 |
* while the bottom-right corner corresponds to: |
|
129 |
* ((imgWidth/texWidth), 0.0) |
|
130 |
*/ |
|
131 |
sy1 = srcOps->height - sy1; |
|
132 |
sy2 = srcOps->height - sy2; |
|
133 |
} |
|
134 |
||
135 |
if (srcOps->textureTarget == GL_TEXTURE_RECTANGLE_ARB) { |
|
136 |
// The GL_ARB_texture_rectangle extension requires that we specify |
|
137 |
// texture coordinates in the range [0,srcw] and [0,srch] instead of |
|
138 |
// [0,1] as we would normally do in the case of GL_TEXTURE_2D |
|
139 |
tx1 = (GLdouble)sx1; |
|
140 |
ty1 = (GLdouble)sy1; |
|
141 |
tx2 = (GLdouble)sx2; |
|
142 |
ty2 = (GLdouble)sy2; |
|
143 |
} else { |
|
144 |
// Otherwise we need to convert the source bounds into the range [0,1] |
|
145 |
tx1 = ((GLdouble)sx1) / srcOps->textureWidth; |
|
146 |
ty1 = ((GLdouble)sy1) / srcOps->textureHeight; |
|
147 |
tx2 = ((GLdouble)sx2) / srcOps->textureWidth; |
|
148 |
ty2 = ((GLdouble)sy2) / srcOps->textureHeight; |
|
149 |
} |
|
150 |
||
151 |
// Note that we call CHECK_PREVIOUS_OP(texTarget) in IsoBlit(), which |
|
152 |
// will call glEnable(texTarget) as necessary. |
|
153 |
j2d_glBindTexture(srcOps->textureTarget, srcOps->textureID); |
|
154 |
OGLC_UPDATE_TEXTURE_FUNCTION(oglc, GL_MODULATE); |
|
155 |
OGLSD_UPDATE_TEXTURE_FILTER(srcOps, hint); |
|
156 |
||
157 |
j2d_glBegin(GL_QUADS); |
|
158 |
j2d_glTexCoord2d(tx1, ty1); j2d_glVertex2d(dx1, dy1); |
|
159 |
j2d_glTexCoord2d(tx2, ty1); j2d_glVertex2d(dx2, dy1); |
|
160 |
j2d_glTexCoord2d(tx2, ty2); j2d_glVertex2d(dx2, dy2); |
|
161 |
j2d_glTexCoord2d(tx1, ty2); j2d_glVertex2d(dx1, dy2); |
|
162 |
j2d_glEnd(); |
|
163 |
} |
|
164 |
||
165 |
/** |
|
166 |
* Inner loop used for copying a source system memory ("Sw") surface to a |
|
167 |
* destination OpenGL "Surface". This method is invoked from |
|
168 |
* OGLBlitLoops_Blit(). |
|
169 |
* |
|
170 |
* The standard glDrawPixels() mechanism is used to copy the source region |
|
171 |
* into the destination region. If the regions have different |
|
172 |
* dimensions, the source will be scaled into the destination |
|
173 |
* as appropriate (only nearest neighbor filtering will be applied for simple |
|
174 |
* scale operations). |
|
175 |
*/ |
|
176 |
static void |
|
177 |
OGLBlitSwToSurface(OGLContext *oglc, SurfaceDataRasInfo *srcInfo, |
|
178 |
OGLPixelFormat *pf, |
|
179 |
jint sx1, jint sy1, jint sx2, jint sy2, |
|
180 |
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2) |
|
181 |
{ |
|
182 |
GLfloat scalex, scaley; |
|
183 |
||
184 |
scalex = ((GLfloat)(dx2-dx1)) / (sx2-sx1); |
|
185 |
scaley = ((GLfloat)(dy2-dy1)) / (sy2-sy1); |
|
186 |
||
187 |
if (oglc->extraAlpha != 1.0f) { |
|
188 |
OGLContext_SetExtraAlpha(oglc->extraAlpha); |
|
189 |
} |
|
190 |
if (!pf->hasAlpha) { |
|
191 |
// if the source surface does not have an alpha channel, |
|
192 |
// we need to ensure that the alpha values are forced to |
|
193 |
// the current extra alpha value (see OGLContext_SetExtraAlpha() |
|
194 |
// for more information) |
|
195 |
j2d_glPixelTransferf(GL_ALPHA_SCALE, 0.0f); |
|
196 |
j2d_glPixelTransferf(GL_ALPHA_BIAS, oglc->extraAlpha); |
|
197 |
} |
|
198 |
||
199 |
// This is a rather intriguing (yet totally valid) hack... If we were to |
|
200 |
// specify a raster position that is outside the surface bounds, the raster |
|
201 |
// position would be invalid and nothing would be rendered. However, we |
|
202 |
// can use a widely known trick to move the raster position outside the |
|
203 |
// surface bounds while maintaining its status as valid. The following |
|
204 |
// call to glBitmap() renders a no-op bitmap, but offsets the current |
|
205 |
// raster position from (0,0) to the desired location of (dx1,-dy1)... |
|
206 |
j2d_glRasterPos2i(0, 0); |
|
207 |
j2d_glBitmap(0, 0, 0, 0, (GLfloat)dx1, (GLfloat)-dy1, NULL); |
|
208 |
||
209 |
j2d_glPixelZoom(scalex, -scaley); |
|
1723
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
210 |
|
58616 | 211 |
GLvoid *pSrc = PtrCoord(srcInfo->rasBase, sx1, srcInfo->pixelStride, |
212 |
sy1, srcInfo->scanStride); |
|
213 |
||
1723
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
214 |
// in case pixel stride is not a multiple of scanline stride the copy |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
215 |
// has to be done line by line (see 6207877) |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
216 |
if (srcInfo->scanStride % srcInfo->pixelStride != 0) { |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
217 |
jint width = sx2-sx1; |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
218 |
jint height = sy2-sy1; |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
219 |
while (height > 0) { |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
220 |
j2d_glDrawPixels(width, 1, pf->format, pf->type, pSrc); |
58616 | 221 |
j2d_glBitmap(0, 0, 0, 0, (GLfloat)0, (GLfloat)-scaley, NULL); |
1723
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
222 |
pSrc = PtrAddBytes(pSrc, srcInfo->scanStride); |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
223 |
height--; |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
224 |
} |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
225 |
} else { |
58616 | 226 |
j2d_glDrawPixels(sx2-sx1, sy2-sy1, pf->format, pf->type, pSrc); |
1723
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
227 |
} |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
228 |
|
2 | 229 |
j2d_glPixelZoom(1.0, 1.0); |
230 |
||
231 |
if (oglc->extraAlpha != 1.0f) { |
|
232 |
OGLContext_SetExtraAlpha(1.0f); |
|
233 |
} |
|
234 |
if (!pf->hasAlpha) { |
|
235 |
// restore scale/bias to their original values |
|
236 |
j2d_glPixelTransferf(GL_ALPHA_SCALE, 1.0f); |
|
237 |
j2d_glPixelTransferf(GL_ALPHA_BIAS, 0.0f); |
|
238 |
} |
|
239 |
} |
|
240 |
||
241 |
/** |
|
242 |
* Inner loop used for copying a source system memory ("Sw") surface or |
|
243 |
* OpenGL "Surface" to a destination OpenGL "Surface", using an OpenGL texture |
|
244 |
* tile as an intermediate surface. This method is invoked from |
|
245 |
* OGLBlitLoops_Blit() for "Sw" surfaces and OGLBlitLoops_IsoBlit() for |
|
246 |
* "Surface" surfaces. |
|
247 |
* |
|
248 |
* This method is used to transform the source surface into the destination. |
|
249 |
* Pixel rectangles cannot be arbitrarily transformed (without the |
|
250 |
* GL_EXT_pixel_transform extension, which is not supported on most modern |
|
251 |
* hardware). However, texture mapped quads do respect the GL_MODELVIEW |
|
252 |
* transform matrix, so we use textures here to perform the transform |
|
253 |
* operation. This method uses a tile-based approach in which a small |
|
254 |
* subregion of the source surface is copied into a cached texture tile. The |
|
255 |
* texture tile is then mapped into the appropriate location in the |
|
256 |
* destination surface. |
|
257 |
* |
|
258 |
* REMIND: this only works well using GL_NEAREST for the filtering mode |
|
259 |
* (GL_LINEAR causes visible stitching problems between tiles, |
|
260 |
* but this can be fixed by making use of texture borders) |
|
261 |
*/ |
|
262 |
static void |
|
263 |
OGLBlitToSurfaceViaTexture(OGLContext *oglc, SurfaceDataRasInfo *srcInfo, |
|
264 |
OGLPixelFormat *pf, OGLSDOps *srcOps, |
|
265 |
jboolean swsurface, jint hint, |
|
266 |
jint sx1, jint sy1, jint sx2, jint sy2, |
|
267 |
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2) |
|
268 |
{ |
|
269 |
GLdouble tx1, ty1, tx2, ty2; |
|
270 |
GLdouble dx, dy, dw, dh, cdw, cdh; |
|
271 |
jint tw, th; |
|
272 |
jint sx, sy, sw, sh; |
|
273 |
GLint glhint = (hint == OGLSD_XFORM_BILINEAR) ? GL_LINEAR : GL_NEAREST; |
|
274 |
jboolean adjustAlpha = (pf != NULL && !pf->hasAlpha); |
|
1723
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
275 |
jboolean slowPath; |
2 | 276 |
|
277 |
if (oglc->blitTextureID == 0) { |
|
278 |
if (!OGLContext_InitBlitTileTexture(oglc)) { |
|
279 |
J2dRlsTraceLn(J2D_TRACE_ERROR, |
|
280 |
"OGLBlitToSurfaceViaTexture: could not init blit tile"); |
|
281 |
return; |
|
282 |
} |
|
283 |
} |
|
284 |
||
285 |
tx1 = 0.0f; |
|
286 |
ty1 = 0.0f; |
|
287 |
tw = OGLC_BLIT_TILE_SIZE; |
|
288 |
th = OGLC_BLIT_TILE_SIZE; |
|
289 |
cdw = (dx2-dx1) / (((GLdouble)(sx2-sx1)) / OGLC_BLIT_TILE_SIZE); |
|
290 |
cdh = (dy2-dy1) / (((GLdouble)(sy2-sy1)) / OGLC_BLIT_TILE_SIZE); |
|
291 |
||
292 |
j2d_glEnable(GL_TEXTURE_2D); |
|
293 |
j2d_glBindTexture(GL_TEXTURE_2D, oglc->blitTextureID); |
|
294 |
OGLC_UPDATE_TEXTURE_FUNCTION(oglc, GL_MODULATE); |
|
295 |
j2d_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glhint); |
|
296 |
j2d_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glhint); |
|
297 |
||
298 |
if (adjustAlpha) { |
|
299 |
// if the source surface does not have an alpha channel, |
|
300 |
// we need to ensure that the alpha values are forced to 1.0f |
|
301 |
j2d_glPixelTransferf(GL_ALPHA_SCALE, 0.0f); |
|
302 |
j2d_glPixelTransferf(GL_ALPHA_BIAS, 1.0f); |
|
303 |
} |
|
304 |
||
1723
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
305 |
// in case pixel stride is not a multiple of scanline stride the copy |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
306 |
// has to be done line by line (see 6207877) |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
307 |
slowPath = srcInfo->scanStride % srcInfo->pixelStride != 0; |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
308 |
|
2 | 309 |
for (sy = sy1, dy = dy1; sy < sy2; sy += th, dy += cdh) { |
310 |
sh = ((sy + th) > sy2) ? (sy2 - sy) : th; |
|
311 |
dh = ((dy + cdh) > dy2) ? (dy2 - dy) : cdh; |
|
312 |
||
313 |
for (sx = sx1, dx = dx1; sx < sx2; sx += tw, dx += cdw) { |
|
314 |
sw = ((sx + tw) > sx2) ? (sx2 - sx) : tw; |
|
315 |
dw = ((dx + cdw) > dx2) ? (dx2 - dx) : cdw; |
|
316 |
||
317 |
tx2 = ((GLdouble)sw) / tw; |
|
318 |
ty2 = ((GLdouble)sh) / th; |
|
319 |
||
320 |
if (swsurface) { |
|
58616 | 321 |
GLvoid *pSrc = PtrCoord(srcInfo->rasBase, |
322 |
sx, srcInfo->pixelStride, |
|
323 |
sy, srcInfo->scanStride); |
|
1723
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
324 |
if (slowPath) { |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
325 |
jint tmph = sh; |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
326 |
while (tmph > 0) { |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
327 |
j2d_glTexSubImage2D(GL_TEXTURE_2D, 0, |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
328 |
0, sh - tmph, sw, 1, |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
329 |
pf->format, pf->type, |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
330 |
pSrc); |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
331 |
pSrc = PtrAddBytes(pSrc, srcInfo->scanStride); |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
332 |
tmph--; |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
333 |
} |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
334 |
} else { |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
335 |
j2d_glTexSubImage2D(GL_TEXTURE_2D, 0, |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
336 |
0, 0, sw, sh, |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
337 |
pf->format, pf->type, |
58616 | 338 |
pSrc); |
1723
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
339 |
} |
2 | 340 |
|
341 |
// the texture image is "right side up", so we align the |
|
342 |
// upper-left texture corner with the upper-left quad corner |
|
343 |
j2d_glBegin(GL_QUADS); |
|
344 |
j2d_glTexCoord2d(tx1, ty1); j2d_glVertex2d(dx, dy); |
|
345 |
j2d_glTexCoord2d(tx2, ty1); j2d_glVertex2d(dx + dw, dy); |
|
346 |
j2d_glTexCoord2d(tx2, ty2); j2d_glVertex2d(dx + dw, dy + dh); |
|
347 |
j2d_glTexCoord2d(tx1, ty2); j2d_glVertex2d(dx, dy + dh); |
|
348 |
j2d_glEnd(); |
|
349 |
} else { |
|
350 |
// this accounts for lower-left origin of the source region |
|
351 |
jint newsx = srcOps->xOffset + sx; |
|
352 |
jint newsy = srcOps->yOffset + srcOps->height - (sy + sh); |
|
353 |
j2d_glCopyTexSubImage2D(GL_TEXTURE_2D, 0, |
|
354 |
0, 0, newsx, newsy, sw, sh); |
|
355 |
||
356 |
// the texture image is "upside down" after the last step, so |
|
357 |
// we align the bottom-left texture corner with the upper-left |
|
358 |
// quad corner (and vice versa) to effectively flip the |
|
359 |
// texture image |
|
360 |
j2d_glBegin(GL_QUADS); |
|
361 |
j2d_glTexCoord2d(tx1, ty2); j2d_glVertex2d(dx, dy); |
|
362 |
j2d_glTexCoord2d(tx2, ty2); j2d_glVertex2d(dx + dw, dy); |
|
363 |
j2d_glTexCoord2d(tx2, ty1); j2d_glVertex2d(dx + dw, dy + dh); |
|
364 |
j2d_glTexCoord2d(tx1, ty1); j2d_glVertex2d(dx, dy + dh); |
|
365 |
j2d_glEnd(); |
|
366 |
} |
|
367 |
} |
|
368 |
} |
|
369 |
||
370 |
if (adjustAlpha) { |
|
371 |
// restore scale/bias to their original values |
|
372 |
j2d_glPixelTransferf(GL_ALPHA_SCALE, 1.0f); |
|
373 |
j2d_glPixelTransferf(GL_ALPHA_BIAS, 0.0f); |
|
374 |
} |
|
375 |
||
376 |
j2d_glDisable(GL_TEXTURE_2D); |
|
377 |
} |
|
378 |
||
379 |
/** |
|
380 |
* Inner loop used for copying a source system memory ("Sw") surface to a |
|
381 |
* destination OpenGL "Texture". This method is invoked from |
|
382 |
* OGLBlitLoops_Blit(). |
|
383 |
* |
|
384 |
* The source surface is effectively loaded into the OpenGL texture object, |
|
385 |
* which must have already been initialized by OGLSD_initTexture(). Note |
|
386 |
* that this method is only capable of copying the source surface into the |
|
387 |
* destination surface (i.e. no scaling or general transform is allowed). |
|
388 |
* This restriction should not be an issue as this method is only used |
|
389 |
* currently to cache a static system memory image into an OpenGL texture in |
|
390 |
* a hidden-acceleration situation. |
|
391 |
*/ |
|
392 |
static void |
|
393 |
OGLBlitSwToTexture(SurfaceDataRasInfo *srcInfo, OGLPixelFormat *pf, |
|
394 |
OGLSDOps *dstOps, |
|
395 |
jint dx1, jint dy1, jint dx2, jint dy2) |
|
396 |
{ |
|
13237
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
397 |
jboolean adjustAlpha = (pf != NULL && !pf->hasAlpha); |
2 | 398 |
j2d_glBindTexture(dstOps->textureTarget, dstOps->textureID); |
13237
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
399 |
|
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
400 |
if (adjustAlpha) { |
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
401 |
// if the source surface does not have an alpha channel, |
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
402 |
// we need to ensure that the alpha values are forced to 1.0f |
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
403 |
j2d_glPixelTransferf(GL_ALPHA_SCALE, 0.0f); |
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
404 |
j2d_glPixelTransferf(GL_ALPHA_BIAS, 1.0f); |
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
405 |
} |
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
406 |
|
1723
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
407 |
// in case pixel stride is not a multiple of scanline stride the copy |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
408 |
// has to be done line by line (see 6207877) |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
409 |
if (srcInfo->scanStride % srcInfo->pixelStride != 0) { |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
410 |
jint width = dx2 - dx1; |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
411 |
jint height = dy2 - dy1; |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
412 |
GLvoid *pSrc = srcInfo->rasBase; |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
413 |
|
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
414 |
while (height > 0) { |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
415 |
j2d_glTexSubImage2D(dstOps->textureTarget, 0, |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
416 |
dx1, dy2 - height, width, 1, |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
417 |
pf->format, pf->type, pSrc); |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
418 |
pSrc = PtrAddBytes(pSrc, srcInfo->scanStride); |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
419 |
height--; |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
420 |
} |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
421 |
} else { |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
422 |
j2d_glTexSubImage2D(dstOps->textureTarget, 0, |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
423 |
dx1, dy1, dx2-dx1, dy2-dy1, |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
424 |
pf->format, pf->type, srcInfo->rasBase); |
4a616c1eac0b
6739267: D3D/OGL: add missing ThreeByteBgr to texture upload blit loop
tdv
parents:
2
diff
changeset
|
425 |
} |
13237
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
426 |
if (adjustAlpha) { |
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
427 |
// restore scale/bias to their original values |
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
428 |
j2d_glPixelTransferf(GL_ALPHA_SCALE, 1.0f); |
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
429 |
j2d_glPixelTransferf(GL_ALPHA_BIAS, 0.0f); |
184b8add9324
7181438: [OGL] Incorrect alpha used, during blit from SW to the texture.
serb
parents:
12047
diff
changeset
|
430 |
} |
2 | 431 |
} |
432 |
||
433 |
/** |
|
434 |
* General blit method for copying a native OpenGL surface (of type "Surface" |
|
435 |
* or "Texture") to another OpenGL "Surface". If texture is JNI_TRUE, this |
|
436 |
* method will invoke the Texture->Surface inner loop; otherwise, one of the |
|
437 |
* Surface->Surface inner loops will be invoked, depending on the transform |
|
438 |
* state. |
|
439 |
* |
|
440 |
* REMIND: we can trick these blit methods into doing XOR simply by passing |
|
441 |
* in the (pixel ^ xorpixel) as the pixel value and preceding the |
|
442 |
* blit with a fillrect... |
|
443 |
*/ |
|
444 |
void |
|
445 |
OGLBlitLoops_IsoBlit(JNIEnv *env, |
|
446 |
OGLContext *oglc, jlong pSrcOps, jlong pDstOps, |
|
447 |
jboolean xform, jint hint, |
|
448 |
jboolean texture, jboolean rtt, |
|
449 |
jint sx1, jint sy1, jint sx2, jint sy2, |
|
450 |
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2) |
|
451 |
{ |
|
452 |
OGLSDOps *srcOps = (OGLSDOps *)jlong_to_ptr(pSrcOps); |
|
453 |
OGLSDOps *dstOps = (OGLSDOps *)jlong_to_ptr(pDstOps); |
|
454 |
SurfaceDataRasInfo srcInfo; |
|
455 |
jint sw = sx2 - sx1; |
|
456 |
jint sh = sy2 - sy1; |
|
457 |
jdouble dw = dx2 - dx1; |
|
458 |
jdouble dh = dy2 - dy1; |
|
459 |
||
460 |
J2dTraceLn(J2D_TRACE_INFO, "OGLBlitLoops_IsoBlit"); |
|
461 |
||
462 |
if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0) { |
|
463 |
J2dTraceLn(J2D_TRACE_WARNING, |
|
464 |
"OGLBlitLoops_IsoBlit: invalid dimensions"); |
|
465 |
return; |
|
466 |
} |
|
467 |
||
468 |
RETURN_IF_NULL(srcOps); |
|
469 |
RETURN_IF_NULL(dstOps); |
|
470 |
RETURN_IF_NULL(oglc); |
|
471 |
||
472 |
srcInfo.bounds.x1 = sx1; |
|
473 |
srcInfo.bounds.y1 = sy1; |
|
474 |
srcInfo.bounds.x2 = sx2; |
|
475 |
srcInfo.bounds.y2 = sy2; |
|
476 |
||
477 |
SurfaceData_IntersectBoundsXYXY(&srcInfo.bounds, |
|
478 |
0, 0, srcOps->width, srcOps->height); |
|
479 |
||
480 |
if (srcInfo.bounds.x2 > srcInfo.bounds.x1 && |
|
481 |
srcInfo.bounds.y2 > srcInfo.bounds.y1) |
|
482 |
{ |
|
483 |
if (srcInfo.bounds.x1 != sx1) { |
|
484 |
dx1 += (srcInfo.bounds.x1 - sx1) * (dw / sw); |
|
485 |
sx1 = srcInfo.bounds.x1; |
|
486 |
} |
|
487 |
if (srcInfo.bounds.y1 != sy1) { |
|
488 |
dy1 += (srcInfo.bounds.y1 - sy1) * (dh / sh); |
|
489 |
sy1 = srcInfo.bounds.y1; |
|
490 |
} |
|
491 |
if (srcInfo.bounds.x2 != sx2) { |
|
492 |
dx2 += (srcInfo.bounds.x2 - sx2) * (dw / sw); |
|
493 |
sx2 = srcInfo.bounds.x2; |
|
494 |
} |
|
495 |
if (srcInfo.bounds.y2 != sy2) { |
|
496 |
dy2 += (srcInfo.bounds.y2 - sy2) * (dh / sh); |
|
497 |
sy2 = srcInfo.bounds.y2; |
|
498 |
} |
|
499 |
||
500 |
J2dTraceLn2(J2D_TRACE_VERBOSE, " texture=%d hint=%d", texture, hint); |
|
501 |
J2dTraceLn4(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", |
|
502 |
sx1, sy1, sx2, sy2); |
|
503 |
J2dTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", |
|
504 |
dx1, dy1, dx2, dy2); |
|
505 |
||
506 |
if (texture) { |
|
507 |
GLint glhint = (hint == OGLSD_XFORM_BILINEAR) ? GL_LINEAR : |
|
508 |
GL_NEAREST; |
|
509 |
CHECK_PREVIOUS_OP(srcOps->textureTarget); |
|
510 |
OGLBlitTextureToSurface(oglc, srcOps, dstOps, rtt, glhint, |
|
511 |
sx1, sy1, sx2, sy2, |
|
512 |
dx1, dy1, dx2, dy2); |
|
513 |
} else { |
|
514 |
jboolean viaTexture; |
|
515 |
if (xform) { |
|
516 |
// we must use the via-texture codepath when there is a xform |
|
517 |
viaTexture = JNI_TRUE; |
|
518 |
} else { |
|
519 |
// look at the vendor to see which codepath is faster |
|
520 |
// (this has been empirically determined; see 5020009) |
|
521 |
switch (OGLC_GET_VENDOR(oglc)) { |
|
522 |
case OGLC_VENDOR_NVIDIA: |
|
523 |
// the via-texture codepath tends to be faster when |
|
524 |
// there is either a simple scale OR an extra alpha |
|
525 |
viaTexture = |
|
526 |
(sx2-sx1) != (jint)(dx2-dx1) || |
|
527 |
(sy2-sy1) != (jint)(dy2-dy1) || |
|
528 |
oglc->extraAlpha != 1.0f; |
|
529 |
break; |
|
530 |
||
531 |
case OGLC_VENDOR_ATI: |
|
532 |
// the via-texture codepath tends to be faster only when |
|
533 |
// there is an extra alpha involved (scaling or not) |
|
534 |
viaTexture = (oglc->extraAlpha != 1.0f); |
|
535 |
break; |
|
536 |
||
537 |
default: |
|
538 |
// just use the glCopyPixels() codepath |
|
539 |
viaTexture = JNI_FALSE; |
|
540 |
break; |
|
541 |
} |
|
542 |
} |
|
543 |
||
544 |
RESET_PREVIOUS_OP(); |
|
545 |
if (viaTexture) { |
|
546 |
OGLBlitToSurfaceViaTexture(oglc, &srcInfo, NULL, srcOps, |
|
547 |
JNI_FALSE, hint, |
|
548 |
sx1, sy1, sx2, sy2, |
|
549 |
dx1, dy1, dx2, dy2); |
|
550 |
} else { |
|
551 |
OGLBlitSurfaceToSurface(oglc, srcOps, dstOps, |
|
552 |
sx1, sy1, sx2, sy2, |
|
553 |
dx1, dy1, dx2, dy2); |
|
554 |
} |
|
555 |
} |
|
556 |
} |
|
557 |
} |
|
558 |
||
559 |
/** |
|
560 |
* General blit method for copying a system memory ("Sw") surface to a native |
|
561 |
* OpenGL surface (of type "Surface" or "Texture"). If texture is JNI_TRUE, |
|
562 |
* this method will invoke the Sw->Texture inner loop; otherwise, one of the |
|
563 |
* Sw->Surface inner loops will be invoked, depending on the transform state. |
|
564 |
*/ |
|
565 |
void |
|
566 |
OGLBlitLoops_Blit(JNIEnv *env, |
|
567 |
OGLContext *oglc, jlong pSrcOps, jlong pDstOps, |
|
568 |
jboolean xform, jint hint, |
|
569 |
jint srctype, jboolean texture, |
|
570 |
jint sx1, jint sy1, jint sx2, jint sy2, |
|
571 |
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2) |
|
572 |
{ |
|
573 |
SurfaceDataOps *srcOps = (SurfaceDataOps *)jlong_to_ptr(pSrcOps); |
|
574 |
OGLSDOps *dstOps = (OGLSDOps *)jlong_to_ptr(pDstOps); |
|
575 |
SurfaceDataRasInfo srcInfo; |
|
576 |
OGLPixelFormat pf = PixelFormats[srctype]; |
|
577 |
jint sw = sx2 - sx1; |
|
578 |
jint sh = sy2 - sy1; |
|
579 |
jdouble dw = dx2 - dx1; |
|
580 |
jdouble dh = dy2 - dy1; |
|
581 |
||
582 |
J2dTraceLn(J2D_TRACE_INFO, "OGLBlitLoops_Blit"); |
|
583 |
||
584 |
if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0 || srctype < 0) { |
|
585 |
J2dTraceLn(J2D_TRACE_WARNING, |
|
586 |
"OGLBlitLoops_Blit: invalid dimensions or srctype"); |
|
587 |
return; |
|
588 |
} |
|
589 |
||
590 |
RETURN_IF_NULL(srcOps); |
|
591 |
RETURN_IF_NULL(dstOps); |
|
592 |
RETURN_IF_NULL(oglc); |
|
593 |
RESET_PREVIOUS_OP(); |
|
594 |
||
595 |
srcInfo.bounds.x1 = sx1; |
|
596 |
srcInfo.bounds.y1 = sy1; |
|
597 |
srcInfo.bounds.x2 = sx2; |
|
598 |
srcInfo.bounds.y2 = sy2; |
|
599 |
||
600 |
if (srcOps->Lock(env, srcOps, &srcInfo, SD_LOCK_READ) != SD_SUCCESS) { |
|
601 |
J2dTraceLn(J2D_TRACE_WARNING, |
|
602 |
"OGLBlitLoops_Blit: could not acquire lock"); |
|
603 |
return; |
|
604 |
} |
|
605 |
||
606 |
if (srcInfo.bounds.x2 > srcInfo.bounds.x1 && |
|
607 |
srcInfo.bounds.y2 > srcInfo.bounds.y1) |
|
608 |
{ |
|
609 |
srcOps->GetRasInfo(env, srcOps, &srcInfo); |
|
610 |
if (srcInfo.rasBase) { |
|
611 |
if (srcInfo.bounds.x1 != sx1) { |
|
612 |
dx1 += (srcInfo.bounds.x1 - sx1) * (dw / sw); |
|
613 |
sx1 = srcInfo.bounds.x1; |
|
614 |
} |
|
615 |
if (srcInfo.bounds.y1 != sy1) { |
|
616 |
dy1 += (srcInfo.bounds.y1 - sy1) * (dh / sh); |
|
617 |
sy1 = srcInfo.bounds.y1; |
|
618 |
} |
|
619 |
if (srcInfo.bounds.x2 != sx2) { |
|
620 |
dx2 += (srcInfo.bounds.x2 - sx2) * (dw / sw); |
|
621 |
sx2 = srcInfo.bounds.x2; |
|
622 |
} |
|
623 |
if (srcInfo.bounds.y2 != sy2) { |
|
624 |
dy2 += (srcInfo.bounds.y2 - sy2) * (dh / sh); |
|
625 |
sy2 = srcInfo.bounds.y2; |
|
626 |
} |
|
627 |
||
628 |
J2dTraceLn3(J2D_TRACE_VERBOSE, " texture=%d srctype=%d hint=%d", |
|
629 |
texture, srctype, hint); |
|
630 |
J2dTraceLn4(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", |
|
631 |
sx1, sy1, sx2, sy2); |
|
632 |
J2dTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", |
|
633 |
dx1, dy1, dx2, dy2); |
|
634 |
||
58616 | 635 |
// Note: we will calculate x/y positions in the raster manually |
636 |
j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); |
|
637 |
j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); |
|
2 | 638 |
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, |
639 |
srcInfo.scanStride / srcInfo.pixelStride); |
|
640 |
j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, pf.alignment); |
|
641 |
||
642 |
if (texture) { |
|
643 |
// These coordinates will always be integers since we |
|
644 |
// only ever do a straight copy from sw to texture. |
|
645 |
// Thus these casts are "safe" - no loss of precision. |
|
646 |
OGLBlitSwToTexture(&srcInfo, &pf, dstOps, |
|
647 |
(jint)dx1, (jint)dy1, (jint)dx2, (jint)dy2); |
|
648 |
} else { |
|
649 |
jboolean viaTexture; |
|
650 |
if (xform) { |
|
651 |
// we must use the via-texture codepath when there |
|
652 |
// is a xform |
|
653 |
viaTexture = JNI_TRUE; |
|
654 |
} else { |
|
655 |
// look at the vendor to see which codepath is faster |
|
656 |
// (this has been empirically determined; see 5020009) |
|
657 |
switch (OGLC_GET_VENDOR(oglc)) { |
|
658 |
case OGLC_VENDOR_NVIDIA: |
|
659 |
// the via-texture codepath tends to be faster when |
|
660 |
// there is either a simple scale OR an extra alpha |
|
661 |
viaTexture = |
|
662 |
(sx2-sx1) != (jint)(dx2-dx1) || |
|
663 |
(sy2-sy1) != (jint)(dy2-dy1) || |
|
664 |
oglc->extraAlpha != 1.0f; |
|
665 |
break; |
|
21229
dfcbcf500680
8024461: [macosx] Java crashed on mac10.9 for swing and 2d function manual test
jchen
parents:
13237
diff
changeset
|
666 |
#ifdef MACOSX |
dfcbcf500680
8024461: [macosx] Java crashed on mac10.9 for swing and 2d function manual test
jchen
parents:
13237
diff
changeset
|
667 |
case OGLC_VENDOR_ATI: |
dfcbcf500680
8024461: [macosx] Java crashed on mac10.9 for swing and 2d function manual test
jchen
parents:
13237
diff
changeset
|
668 |
// see 8024461 |
dfcbcf500680
8024461: [macosx] Java crashed on mac10.9 for swing and 2d function manual test
jchen
parents:
13237
diff
changeset
|
669 |
viaTexture = JNI_TRUE; |
dfcbcf500680
8024461: [macosx] Java crashed on mac10.9 for swing and 2d function manual test
jchen
parents:
13237
diff
changeset
|
670 |
break; |
dfcbcf500680
8024461: [macosx] Java crashed on mac10.9 for swing and 2d function manual test
jchen
parents:
13237
diff
changeset
|
671 |
#endif |
28076
64c048b63cea
8059944: [OGL] Metrics for a method choice copying of texture should be improved
serb
parents:
26751
diff
changeset
|
672 |
case OGLC_VENDOR_INTEL: |
64c048b63cea
8059944: [OGL] Metrics for a method choice copying of texture should be improved
serb
parents:
26751
diff
changeset
|
673 |
viaTexture = JNI_TRUE; |
64c048b63cea
8059944: [OGL] Metrics for a method choice copying of texture should be improved
serb
parents:
26751
diff
changeset
|
674 |
break; |
2 | 675 |
default: |
676 |
// just use the glDrawPixels() codepath |
|
677 |
viaTexture = JNI_FALSE; |
|
678 |
break; |
|
679 |
} |
|
680 |
} |
|
681 |
||
682 |
if (viaTexture) { |
|
683 |
OGLBlitToSurfaceViaTexture(oglc, &srcInfo, &pf, NULL, |
|
684 |
JNI_TRUE, hint, |
|
685 |
sx1, sy1, sx2, sy2, |
|
686 |
dx1, dy1, dx2, dy2); |
|
687 |
} else { |
|
688 |
OGLBlitSwToSurface(oglc, &srcInfo, &pf, |
|
689 |
sx1, sy1, sx2, sy2, |
|
690 |
dx1, dy1, dx2, dy2); |
|
691 |
} |
|
692 |
} |
|
693 |
||
694 |
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); |
|
695 |
j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 4); |
|
696 |
} |
|
697 |
SurfaceData_InvokeRelease(env, srcOps, &srcInfo); |
|
698 |
} |
|
699 |
SurfaceData_InvokeUnlock(env, srcOps, &srcInfo); |
|
700 |
} |
|
701 |
||
702 |
/** |
|
25127 | 703 |
* This method makes vertical flip of the provided area of Surface and convert |
704 |
* pixel's data from argbPre to argb format if requested. |
|
705 |
*/ |
|
706 |
void flip(void *pDst, juint w, juint h, jint scanStride, jboolean convert) { |
|
707 |
const size_t clippedStride = 4 * w; |
|
708 |
void *tempRow = (h > 1 && !convert) ? malloc(clippedStride) : NULL; |
|
709 |
juint i = 0; |
|
710 |
juint step = 0; |
|
711 |
// vertical flip and convert argbpre to argb if necessary |
|
712 |
for (; i < h / 2; ++i) { |
|
713 |
juint *r1 = PtrAddBytes(pDst, (i * scanStride)); |
|
714 |
juint *r2 = PtrAddBytes(pDst, (h - i - 1) * scanStride); |
|
715 |
if (tempRow) { |
|
716 |
// fast path |
|
717 |
memcpy(tempRow, r1, clippedStride); |
|
718 |
memcpy(r1, r2, clippedStride); |
|
719 |
memcpy(r2, tempRow, clippedStride); |
|
720 |
} else { |
|
721 |
// slow path |
|
722 |
for (step = 0; step < w; ++step) { |
|
723 |
juint tmp = r1[step]; |
|
724 |
if (convert) { |
|
725 |
LoadIntArgbPreTo1IntArgb(r2, 0, step, r1[step]); |
|
726 |
LoadIntArgbPreTo1IntArgb(&tmp, 0, 0, r2[step]); |
|
727 |
} else { |
|
728 |
r1[step] = r2[step]; |
|
729 |
r2[step] = tmp; |
|
730 |
} |
|
731 |
} |
|
732 |
} |
|
733 |
} |
|
734 |
// convert the middle line if necessary |
|
735 |
if (convert && h % 2) { |
|
736 |
juint *r1 = PtrAddBytes(pDst, (i * scanStride)); |
|
737 |
for (step = 0; step < w; ++step) { |
|
738 |
LoadIntArgbPreTo1IntArgb(r1, 0, step, r1[step]); |
|
739 |
} |
|
740 |
} |
|
741 |
if (tempRow) { |
|
742 |
free(tempRow); |
|
743 |
} |
|
744 |
} |
|
745 |
||
746 |
/** |
|
2 | 747 |
* Specialized blit method for copying a native OpenGL "Surface" (pbuffer, |
748 |
* window, etc.) to a system memory ("Sw") surface. |
|
749 |
*/ |
|
750 |
void |
|
751 |
OGLBlitLoops_SurfaceToSwBlit(JNIEnv *env, OGLContext *oglc, |
|
752 |
jlong pSrcOps, jlong pDstOps, jint dsttype, |
|
753 |
jint srcx, jint srcy, jint dstx, jint dsty, |
|
754 |
jint width, jint height) |
|
755 |
{ |
|
756 |
OGLSDOps *srcOps = (OGLSDOps *)jlong_to_ptr(pSrcOps); |
|
757 |
SurfaceDataOps *dstOps = (SurfaceDataOps *)jlong_to_ptr(pDstOps); |
|
758 |
SurfaceDataRasInfo srcInfo, dstInfo; |
|
759 |
OGLPixelFormat pf = PixelFormats[dsttype]; |
|
760 |
||
761 |
J2dTraceLn(J2D_TRACE_INFO, "OGLBlitLoops_SurfaceToSwBlit"); |
|
762 |
||
763 |
if (width <= 0 || height <= 0) { |
|
764 |
J2dTraceLn(J2D_TRACE_WARNING, |
|
765 |
"OGLBlitLoops_SurfaceToSwBlit: dimensions are non-positive"); |
|
766 |
return; |
|
767 |
} |
|
768 |
||
769 |
RETURN_IF_NULL(srcOps); |
|
770 |
RETURN_IF_NULL(dstOps); |
|
771 |
RETURN_IF_NULL(oglc); |
|
772 |
RESET_PREVIOUS_OP(); |
|
773 |
||
774 |
srcInfo.bounds.x1 = srcx; |
|
775 |
srcInfo.bounds.y1 = srcy; |
|
776 |
srcInfo.bounds.x2 = srcx + width; |
|
777 |
srcInfo.bounds.y2 = srcy + height; |
|
778 |
dstInfo.bounds.x1 = dstx; |
|
779 |
dstInfo.bounds.y1 = dsty; |
|
780 |
dstInfo.bounds.x2 = dstx + width; |
|
781 |
dstInfo.bounds.y2 = dsty + height; |
|
782 |
||
783 |
if (dstOps->Lock(env, dstOps, &dstInfo, SD_LOCK_WRITE) != SD_SUCCESS) { |
|
784 |
J2dTraceLn(J2D_TRACE_WARNING, |
|
785 |
"OGLBlitLoops_SurfaceToSwBlit: could not acquire dst lock"); |
|
786 |
return; |
|
787 |
} |
|
788 |
||
789 |
SurfaceData_IntersectBoundsXYXY(&srcInfo.bounds, |
|
790 |
0, 0, srcOps->width, srcOps->height); |
|
791 |
SurfaceData_IntersectBlitBounds(&dstInfo.bounds, &srcInfo.bounds, |
|
792 |
srcx - dstx, srcy - dsty); |
|
793 |
||
794 |
if (srcInfo.bounds.x2 > srcInfo.bounds.x1 && |
|
795 |
srcInfo.bounds.y2 > srcInfo.bounds.y1) |
|
796 |
{ |
|
797 |
dstOps->GetRasInfo(env, dstOps, &dstInfo); |
|
798 |
if (dstInfo.rasBase) { |
|
799 |
void *pDst = dstInfo.rasBase; |
|
800 |
||
801 |
srcx = srcInfo.bounds.x1; |
|
802 |
srcy = srcInfo.bounds.y1; |
|
803 |
dstx = dstInfo.bounds.x1; |
|
804 |
dsty = dstInfo.bounds.y1; |
|
805 |
width = srcInfo.bounds.x2 - srcInfo.bounds.x1; |
|
806 |
height = srcInfo.bounds.y2 - srcInfo.bounds.y1; |
|
807 |
||
25127 | 808 |
pDst = PtrAddBytes(pDst, dstx * dstInfo.pixelStride); |
809 |
pDst = PtrAddBytes(pDst, dsty * dstInfo.scanStride); |
|
810 |
||
2 | 811 |
j2d_glPixelStorei(GL_PACK_ROW_LENGTH, |
812 |
dstInfo.scanStride / dstInfo.pixelStride); |
|
813 |
j2d_glPixelStorei(GL_PACK_ALIGNMENT, pf.alignment); |
|
12047
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
814 |
#ifdef MACOSX |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
815 |
if (srcOps->isOpaque) { |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
816 |
// For some reason Apple's OpenGL implementation will |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
817 |
// read back zero values from the alpha channel of an |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
818 |
// opaque surface when using glReadPixels(), so here we |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
819 |
// force the resulting pixels to be fully opaque. |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
820 |
j2d_glPixelTransferf(GL_ALPHA_BIAS, 1.0); |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
821 |
} |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
822 |
#endif |
2 | 823 |
|
824 |
J2dTraceLn4(J2D_TRACE_VERBOSE, " sx=%d sy=%d w=%d h=%d", |
|
825 |
srcx, srcy, width, height); |
|
826 |
J2dTraceLn2(J2D_TRACE_VERBOSE, " dx=%d dy=%d", |
|
827 |
dstx, dsty); |
|
828 |
||
829 |
// this accounts for lower-left origin of the source region |
|
830 |
srcx = srcOps->xOffset + srcx; |
|
25127 | 831 |
srcy = srcOps->yOffset + srcOps->height - srcy - height; |
2 | 832 |
|
25127 | 833 |
// Note that glReadPixels() is extremely slow! |
834 |
// So we call it only once and flip the image using memcpy. |
|
835 |
j2d_glReadPixels(srcx, srcy, width, height, |
|
836 |
pf.format, pf.type, pDst); |
|
837 |
// It was checked above that width and height are positive. |
|
838 |
flip(pDst, (juint) width, (juint) height, dstInfo.scanStride, |
|
839 |
!pf.isPremult && !srcOps->isOpaque); |
|
12047
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
840 |
#ifdef MACOSX |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
841 |
if (srcOps->isOpaque) { |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
842 |
j2d_glPixelTransferf(GL_ALPHA_BIAS, 0.0); |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
843 |
} |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
844 |
#endif |
2 | 845 |
j2d_glPixelStorei(GL_PACK_ROW_LENGTH, 0); |
846 |
j2d_glPixelStorei(GL_PACK_ALIGNMENT, 4); |
|
847 |
} |
|
848 |
SurfaceData_InvokeRelease(env, dstOps, &dstInfo); |
|
849 |
} |
|
850 |
SurfaceData_InvokeUnlock(env, dstOps, &dstInfo); |
|
851 |
} |
|
852 |
||
853 |
void |
|
854 |
OGLBlitLoops_CopyArea(JNIEnv *env, |
|
855 |
OGLContext *oglc, OGLSDOps *dstOps, |
|
856 |
jint x, jint y, jint width, jint height, |
|
857 |
jint dx, jint dy) |
|
858 |
{ |
|
859 |
SurfaceDataBounds srcBounds, dstBounds; |
|
860 |
||
861 |
J2dTraceLn(J2D_TRACE_INFO, "OGLBlitLoops_CopyArea"); |
|
862 |
||
863 |
RETURN_IF_NULL(oglc); |
|
864 |
RETURN_IF_NULL(dstOps); |
|
865 |
RESET_PREVIOUS_OP(); |
|
866 |
||
867 |
J2dTraceLn4(J2D_TRACE_VERBOSE, " x=%d y=%d w=%d h=%d", |
|
868 |
x, y, width, height); |
|
869 |
J2dTraceLn2(J2D_TRACE_VERBOSE, " dx=%d dy=%d", |
|
870 |
dx, dy); |
|
871 |
||
872 |
srcBounds.x1 = x; |
|
873 |
srcBounds.y1 = y; |
|
874 |
srcBounds.x2 = srcBounds.x1 + width; |
|
875 |
srcBounds.y2 = srcBounds.y1 + height; |
|
876 |
dstBounds.x1 = x + dx; |
|
877 |
dstBounds.y1 = y + dy; |
|
878 |
dstBounds.x2 = dstBounds.x1 + width; |
|
879 |
dstBounds.y2 = dstBounds.y1 + height; |
|
880 |
||
881 |
// 6430601: manually clip src/dst parameters to work around |
|
882 |
// some bugs in Sun's and Apple's OpenGL implementations |
|
883 |
// (it's a good idea to restrict the source parameters anyway, since |
|
884 |
// passing out of range parameters to glCopyPixels() will result in |
|
885 |
// an OpenGL error) |
|
886 |
SurfaceData_IntersectBoundsXYXY(&srcBounds, |
|
887 |
0, 0, dstOps->width, dstOps->height); |
|
888 |
SurfaceData_IntersectBoundsXYXY(&dstBounds, |
|
889 |
0, 0, dstOps->width, dstOps->height); |
|
890 |
SurfaceData_IntersectBlitBounds(&dstBounds, &srcBounds, -dx, -dy); |
|
891 |
||
892 |
if (dstBounds.x1 < dstBounds.x2 && dstBounds.y1 < dstBounds.y2) { |
|
12047
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
893 |
#ifdef MACOSX |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
894 |
if (dstOps->isOpaque) { |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
895 |
// For some reason Apple's OpenGL implementation will fail |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
896 |
// to render glCopyPixels() when the src/dst rectangles are |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
897 |
// overlapping and glColorMask() has disabled writes to the |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
898 |
// alpha channel. The workaround is to temporarily re-enable |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
899 |
// the alpha channel during the glCopyPixels() operation. |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
900 |
j2d_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
901 |
} |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
902 |
#endif |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
903 |
|
2 | 904 |
OGLBlitSurfaceToSurface(oglc, dstOps, dstOps, |
905 |
srcBounds.x1, srcBounds.y1, |
|
906 |
srcBounds.x2, srcBounds.y2, |
|
907 |
dstBounds.x1, dstBounds.y1, |
|
908 |
dstBounds.x2, dstBounds.y2); |
|
12047
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
909 |
#ifdef MACOSX |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
910 |
if (dstOps->isOpaque) { |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
911 |
j2d_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
912 |
} |
320a714614e9
7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
5506
diff
changeset
|
913 |
#endif |
2 | 914 |
} |
915 |
} |
|
916 |
||
917 |
#endif /* !HEADLESS */ |