Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/native/common/java2d/opengl/OGLVertexCache.c
41159 views
1
/*
2
* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
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
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
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
*
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.
24
*/
25
26
#ifndef HEADLESS
27
28
#include <stdlib.h>
29
#include <string.h>
30
31
#include "sun_java2d_SunGraphics2D.h"
32
33
#include "OGLPaints.h"
34
#include "OGLVertexCache.h"
35
36
typedef struct _J2DVertex {
37
jfloat tx, ty;
38
jubyte r, g, b, a;
39
jfloat dx, dy;
40
} J2DVertex;
41
42
static J2DVertex *vertexCache = NULL;
43
static jint vertexCacheIndex = 0;
44
45
static GLuint maskCacheTexID = 0;
46
static jint maskCacheIndex = 0;
47
48
#define OGLVC_ADD_VERTEX(TX, TY, R, G, B, A, DX, DY) \
49
do { \
50
J2DVertex *v = &vertexCache[vertexCacheIndex++]; \
51
v->tx = TX; \
52
v->ty = TY; \
53
v->r = R; \
54
v->g = G; \
55
v->b = B; \
56
v->a = A; \
57
v->dx = DX; \
58
v->dy = DY; \
59
} while (0)
60
61
#define OGLVC_ADD_QUAD(TX1, TY1, TX2, TY2, DX1, DY1, DX2, DY2, R, G, B, A) \
62
do { \
63
OGLVC_ADD_VERTEX(TX1, TY1, R, G, B, A, DX1, DY1); \
64
OGLVC_ADD_VERTEX(TX2, TY1, R, G, B, A, DX2, DY1); \
65
OGLVC_ADD_VERTEX(TX2, TY2, R, G, B, A, DX2, DY2); \
66
OGLVC_ADD_VERTEX(TX1, TY2, R, G, B, A, DX1, DY2); \
67
} while (0)
68
69
jboolean
70
OGLVertexCache_InitVertexCache(OGLContext *oglc)
71
{
72
J2dTraceLn(J2D_TRACE_INFO, "OGLVertexCache_InitVertexCache");
73
74
if (vertexCache == NULL) {
75
vertexCache = (J2DVertex *)malloc(OGLVC_MAX_INDEX * sizeof(J2DVertex));
76
if (vertexCache == NULL) {
77
return JNI_FALSE;
78
}
79
}
80
81
if (!oglc->vertexCacheEnabled) {
82
j2d_glTexCoordPointer(2, GL_FLOAT,
83
sizeof(J2DVertex), vertexCache);
84
j2d_glColorPointer(4, GL_UNSIGNED_BYTE,
85
sizeof(J2DVertex), ((jfloat *)vertexCache) + 2);
86
j2d_glVertexPointer(2, GL_FLOAT,
87
sizeof(J2DVertex), ((jfloat *)vertexCache) + 3);
88
89
j2d_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
90
j2d_glEnableClientState(GL_COLOR_ARRAY);
91
j2d_glEnableClientState(GL_VERTEX_ARRAY);
92
93
oglc->vertexCacheEnabled = JNI_TRUE;
94
}
95
96
return JNI_TRUE;
97
}
98
99
void
100
OGLVertexCache_FlushVertexCache()
101
{
102
J2dTraceLn(J2D_TRACE_INFO, "OGLVertexCache_FlushVertexCache");
103
104
if (vertexCacheIndex > 0) {
105
j2d_glDrawArrays(GL_QUADS, 0, vertexCacheIndex);
106
}
107
vertexCacheIndex = 0;
108
}
109
110
/**
111
* This method is somewhat hacky, but necessary for the foreseeable future.
112
* The problem is the way OpenGL handles color values in vertex arrays. When
113
* a vertex in a vertex array contains a color, and then the vertex array
114
* is rendered via glDrawArrays(), the global OpenGL color state is actually
115
* modified each time a vertex is rendered. This means that after all
116
* vertices have been flushed, the global OpenGL color state will be set to
117
* the color of the most recently rendered element in the vertex array.
118
*
119
* The reason this is a problem for us is that we do not want to flush the
120
* vertex array (in the case of mask/glyph operations) or issue a glEnd()
121
* (in the case of non-antialiased primitives) everytime the current color
122
* changes, which would defeat any benefit from batching in the first place.
123
* We handle this in practice by not calling CHECK/RESET_PREVIOUS_OP() when
124
* the simple color state is changing in OGLPaints_SetColor(). This is
125
* problematic for vertex caching because we may end up with the following
126
* situation, for example:
127
* SET_COLOR (orange)
128
* MASK_FILL
129
* MASK_FILL
130
* SET_COLOR (blue; remember, this won't cause a flush)
131
* FILL_RECT (this will cause the vertex array to be flushed)
132
*
133
* In this case, we would actually end up rendering an orange FILL_RECT,
134
* not a blue one as intended, because flushing the vertex cache flush would
135
* override the color state from the most recent SET_COLOR call.
136
*
137
* Long story short, the easiest way to resolve this problem is to call
138
* this method just after disabling the mask/glyph cache, which will ensure
139
* that the appropriate color state is restored.
140
*/
141
void
142
OGLVertexCache_RestoreColorState(OGLContext *oglc)
143
{
144
if (oglc->paintState == sun_java2d_SunGraphics2D_PAINT_ALPHACOLOR) {
145
OGLPaints_SetColor(oglc, oglc->pixel);
146
}
147
}
148
149
static jboolean
150
OGLVertexCache_InitMaskCache()
151
{
152
J2dTraceLn(J2D_TRACE_INFO, "OGLVertexCache_InitMaskCache");
153
154
maskCacheTexID =
155
OGLContext_CreateBlitTexture(GL_INTENSITY8, GL_LUMINANCE,
156
OGLVC_MASK_CACHE_WIDTH_IN_TEXELS,
157
OGLVC_MASK_CACHE_HEIGHT_IN_TEXELS);
158
159
// init special fully opaque tile in the upper-right corner of
160
// the mask cache texture
161
{
162
GLubyte allOnes[OGLVC_MASK_CACHE_TILE_SIZE];
163
memset(allOnes, 0xff, OGLVC_MASK_CACHE_TILE_SIZE);
164
j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
165
OGLVC_MASK_CACHE_SPECIAL_TILE_X,
166
OGLVC_MASK_CACHE_SPECIAL_TILE_Y,
167
OGLVC_MASK_CACHE_TILE_WIDTH,
168
OGLVC_MASK_CACHE_TILE_HEIGHT,
169
GL_LUMINANCE, GL_UNSIGNED_BYTE, allOnes);
170
}
171
172
return JNI_TRUE;
173
}
174
175
void
176
OGLVertexCache_EnableMaskCache(OGLContext *oglc)
177
{
178
J2dTraceLn(J2D_TRACE_INFO, "OGLVertexCache_EnableMaskCache");
179
180
if (!OGLVertexCache_InitVertexCache(oglc)) {
181
return;
182
}
183
184
if (maskCacheTexID == 0) {
185
if (!OGLVertexCache_InitMaskCache()) {
186
return;
187
}
188
}
189
190
j2d_glEnable(GL_TEXTURE_2D);
191
j2d_glBindTexture(GL_TEXTURE_2D, maskCacheTexID);
192
OGLC_UPDATE_TEXTURE_FUNCTION(oglc, GL_MODULATE);
193
j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
194
}
195
196
void
197
OGLVertexCache_DisableMaskCache(OGLContext *oglc)
198
{
199
J2dTraceLn(J2D_TRACE_INFO, "OGLVertexCache_DisableMaskCache");
200
201
OGLVertexCache_FlushVertexCache();
202
OGLVertexCache_RestoreColorState(oglc);
203
204
j2d_glDisable(GL_TEXTURE_2D);
205
j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
206
j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
207
j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
208
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
209
210
maskCacheIndex = 0;
211
}
212
213
void
214
OGLVertexCache_AddMaskQuad(OGLContext *oglc,
215
jint srcx, jint srcy,
216
jint dstx, jint dsty,
217
jint width, jint height,
218
jint maskscan, void *mask)
219
{
220
jfloat tx1, ty1, tx2, ty2;
221
jfloat dx1, dy1, dx2, dy2;
222
223
J2dTraceLn1(J2D_TRACE_INFO, "OGLVertexCache_AddMaskQuad: %d",
224
maskCacheIndex);
225
226
if (maskCacheIndex >= OGLVC_MASK_CACHE_MAX_INDEX ||
227
vertexCacheIndex >= OGLVC_MAX_INDEX)
228
{
229
OGLVertexCache_FlushVertexCache();
230
maskCacheIndex = 0;
231
}
232
233
if (mask != NULL) {
234
jint texx = OGLVC_MASK_CACHE_TILE_WIDTH *
235
(maskCacheIndex % OGLVC_MASK_CACHE_WIDTH_IN_TILES);
236
jint texy = OGLVC_MASK_CACHE_TILE_HEIGHT *
237
(maskCacheIndex / OGLVC_MASK_CACHE_WIDTH_IN_TILES);
238
239
// update the source pointer offsets
240
j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, srcx);
241
j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, srcy);
242
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, maskscan);
243
244
// copy alpha mask into texture tile
245
j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
246
texx, texy, width, height,
247
GL_LUMINANCE, GL_UNSIGNED_BYTE, mask);
248
249
tx1 = ((jfloat)texx) / OGLVC_MASK_CACHE_WIDTH_IN_TEXELS;
250
ty1 = ((jfloat)texy) / OGLVC_MASK_CACHE_HEIGHT_IN_TEXELS;
251
252
maskCacheIndex++;
253
} else {
254
// use special fully opaque tile
255
tx1 = ((jfloat)OGLVC_MASK_CACHE_SPECIAL_TILE_X) /
256
OGLVC_MASK_CACHE_WIDTH_IN_TEXELS;
257
ty1 = ((jfloat)OGLVC_MASK_CACHE_SPECIAL_TILE_Y) /
258
OGLVC_MASK_CACHE_HEIGHT_IN_TEXELS;
259
}
260
261
tx2 = tx1 + (((jfloat)width) / OGLVC_MASK_CACHE_WIDTH_IN_TEXELS);
262
ty2 = ty1 + (((jfloat)height) / OGLVC_MASK_CACHE_HEIGHT_IN_TEXELS);
263
264
dx1 = (jfloat)dstx;
265
dy1 = (jfloat)dsty;
266
dx2 = dx1 + width;
267
dy2 = dy1 + height;
268
269
OGLVC_ADD_QUAD(tx1, ty1, tx2, ty2,
270
dx1, dy1, dx2, dy2,
271
oglc->r, oglc->g, oglc->b, oglc->a);
272
}
273
274
void
275
OGLVertexCache_AddGlyphQuad(OGLContext *oglc,
276
jfloat tx1, jfloat ty1, jfloat tx2, jfloat ty2,
277
jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2)
278
{
279
J2dTraceLn(J2D_TRACE_INFO, "OGLVertexCache_AddGlyphQuad");
280
281
if (vertexCacheIndex >= OGLVC_MAX_INDEX) {
282
OGLVertexCache_FlushVertexCache();
283
}
284
285
OGLVC_ADD_QUAD(tx1, ty1, tx2, ty2,
286
dx1, dy1, dx2, dy2,
287
oglc->r, oglc->g, oglc->b, oglc->a);
288
}
289
290
#endif /* !HEADLESS */
291
292