aboutsummaryrefslogtreecommitdiff
path: root/src/windows/native/sun/java2d/d3d/D3DContext.h
blob: c4313c101c2e30df6ff6a453beeeb0987df6ece8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
/*
 * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

#ifndef D3DCONTEXT_H
#define D3DCONTEXT_H

#include "java_awt_Transparency.h"
#include "sun_java2d_d3d_D3DContext.h"
#include "ddrawObject.h"
extern "C" {
#include "glyphblitting.h"
#include "AccelGlyphCache.h"
}
#include "j2d_md.h"


// - State switching optimizations -----------------------------------

/**
 * The goal is to reduce device state switching as much as possible.
 * This means: don't reset the texture if not needed, don't change
 * the texture stage states unless necessary.
 * For this we need to track the current device state. So each operation
 * supplies its own operation type to BeginScene, which updates the state
 * as necessary.
 *
 * Another optimization is to use a single vertex format for
 * all primitives.
 *
 * See D3DContext::UpdateState() and D3DContext::BeginScene() for
 * more information.
 */

// The state is undefined, assume that complete initialization is
// needed.
#define STATE_UNDEFINED          (0 << 0)
// Current state uses texture mapping
#define STATE_TEXTURE            (1 << 0)
// Texture stage state which is used when mask is involved
// (text rendering, maskfill)
#define STATE_TEXTURE_STAGE_MASK (1 << 1)
// Texture stage state which is used when doing texture
// mapping in blits
#define STATE_TEXTURE_STAGE_BLIT (1 << 2)
// Texture stage state which is used when not doing
// texture mapping, only use diffuse color
#define STATE_TEXTURE_STAGE_POLY (1 << 3)
// Texture mapping operation which involves mask texture
#define STATE_MASKOP             (STATE_TEXTURE|STATE_TEXTURE_STAGE_MASK)
// Texture mapping operation which involves image texture
#define STATE_BLITOP             (STATE_TEXTURE|STATE_TEXTURE_STAGE_BLIT)
// Rendering operation which doesn't use texture mapping
#define STATE_RENDEROP           (STATE_TEXTURE_STAGE_POLY)

// The max. stage number we currently use (could not be
// larger than 7)
#define MAX_USED_TEXTURE_STAGE 0

// - Texture pixel format table  -------------------------------------
#define TR_OPAQUE      java_awt_Transparency_OPAQUE
#define TR_BITMASK     java_awt_Transparency_BITMASK
#define TR_TRANSLUCENT java_awt_Transparency_TRANSLUCENT

// depth indices for the D3DTextureTable type
#define DEPTH16_IDX 0
#define DEPTH24_IDX 1
#define DEPTH32_IDX 2
#define DEPTH_MAX_IDX 3

// corresponding transparency indices for the D3DTextureTable type
#define TR_OPAQUE_IDX 0
#define TR_BITMASK_IDX 1
#define TR_TRANSLUCENT_IDX 2
#define TR_MAX_IDX 3

typedef struct
{
    DDPIXELFORMAT pddpf;
    jint  pfType;
} D3DTextureTableCell;

// texture table:
// [transparency={OPAQUE,BITMASK,TRANCLUCENT},depth={16,24,32}]
typedef D3DTextureTableCell D3DTextureTable[TR_MAX_IDX][DEPTH_MAX_IDX];

// - D3DContext class  -----------------------------------------------

/**
 * This class provides the following functionality:
 *  - holds the state of D3DContext java class (current pixel color,
 *    alpha compositing mode, extra alpha)
 *  - provides access to IDirect3DDevice7 interface (creation,
 *    disposal, exclusive access)
 *  - handles state changes of the direct3d device (transform,
 *    compositing mode, current texture)
 *  - provides means of creating textures, plain surfaces
 *  - holds a glyph cache texture for the associated device
 *  - implements primitives batching mechanism
 */
class D3DContext {
public:
    /**
     * Creates and returns D3DContext instance. If created context was
     * unable to initialize d3d device or if the device tests failed,
     * returns NULL.
     */
    static D3DContext* CreateD3DContext(DDraw *ddObject, DXObject* dxObject);
    /**
     * Releases the old device (if there was one) and all associated
     * resources, re-creates, initializes and tests the new device.
     *
     * If the device doesn't pass the test, it's released.
     *
     * Used when the context is first created, and then after a
     * display change event.
     *
     * Note that this method also does the necessary registry checks,
     * and if the registry shows that we've crashed when attempting
     * to initialize and test the device last time, it doesn't attempt
     * to create/init/test the device.
     */
    void    CreateD3DDevice();
    void    Release3DDevice();
    virtual ~D3DContext();

    /**
     * Stores a weak reference of passed D3DContext object.
     * This method is called from _getNativeDeviceCaps method, and does the
     * association of the native D3DContext with the corresponding java object.
     * We need a reference to the java object so it can be notified when
     * the native context is released or recreated.
     *
     * See jobject jD3DContext field
     */
    void SetJavaContext(JNIEnv *env, jobject jd3dc);

    /**
     * Methods to get/release exclusive access to the direct3d device
     * interface. Note that some methods of this class assume that the
     * lock is already taken. They're marked with 'NOLOCK' comment.
     * Those methods not dealing with the d3d device interface are not
     * required to obtain the lock (and not marked with NOLOCK)
     */
    void GetExclusiveAccess() { CRITICAL_SECTION_ENTER(deviceLock);}
    void ReleaseExclusiveAccess() { CRITICAL_SECTION_LEAVE(deviceLock);}

    // methods replicating java-level D3DContext objext
    void SetColor(jint eargb, jint flags);
    void SetAlphaComposite(jint rule, jfloat extraAlpha, jint flags);
    void ResetComposite();

    // Glyph cache-related methods
    HRESULT /*NOLOCK*/ InitGlyphCache();
    HRESULT /*NOLOCK*/ GlyphCacheAdd(JNIEnv *env, GlyphInfo *glyph);
    HRESULT /*NOLOCK*/ UploadImageToTexture(DXSurface *texture, jubyte *pixels,
                                            jint dstx, jint dsty,
                                            jint srcx, jint srcy,
                                            jint srcWidth, jint srcHeight,
                                            jint srcStride);
    DXSurface /*NOLOCK*/ *GetGlyphCacheTexture() { return lpGlyphCacheTexture; }
    DXSurface /*NOLOCK*/ *GetMaskTexture();
    GlyphCacheInfo *GetGlyphCache() { return glyphCache; }

    HRESULT CreateSurface(JNIEnv *env,
                          jint width, jint height, jint depth,
                          jint transparency, jint d3dSurfaceType,
                          DXSurface** dxSurface, jint* pType);

    /**
     * Attaches a depth buffer to the specified dxSurface.
     * If depthBufferFormat is not initialized (depthBufferFormat.dwSize == 0),
     * it will be initialized at the time of the call.
     *
     * If the buffer for this surface already exists, a "lost" status of the
     * depth buffer is returned.
     */
    HRESULT AttachDepthBuffer(DXSurface *dxSurface);

    // methods for dealing with device capabilities as determined by
    // methods in D3DRuntimeTest
    int GetDeviceCaps() { return deviceCaps; }
    void SetDeviceCaps(int caps) { deviceCaps = caps; }

    // Returns the texture pixel format table
    D3DTextureTable &GetTextureTable() { return textureTable; }

    DDrawSurface *GetTargetSurface() { return ddTargetSurface; }
    IDirect3DDevice7 *Get3DDevice() { return d3dDevice; }

    // IDirect3DDevice7-delegation methods

    /**
     * This method only sets the texture if it's not already set.
     */
    HRESULT /*NOLOCK*/ SetTexture(DXSurface *dxSurface, DWORD dwStage = 0);
    HRESULT SetRenderTarget(DDrawSurface *lpSurface);
    HRESULT SetTransform(jobject xform,
                         jdouble m00, jdouble m10,
                         jdouble m01, jdouble m11,
                         jdouble m02, jdouble m12);
    HRESULT SetClip(JNIEnv *env, jobject clip,
                    jboolean isRect,
                    int x1, int y1, int x2, int y2);

    DWORD GetMinTextureWidth() { return d3dDevDesc.dwMinTextureWidth; }
    DWORD GetMinTextureHeight() { return d3dDevDesc.dwMinTextureHeight; }
    DWORD GetMaxTextureWidth() { return d3dDevDesc.dwMaxTextureWidth; }
    DWORD GetMaxTextureHeight() { return d3dDevDesc.dwMaxTextureHeight; }
    DWORD GetMaxTextureAspectRatio()
        { return d3dDevDesc.dwMaxTextureAspectRatio; };
    BOOL IsPow2TexturesOnly()
        { return d3dDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2; };
    BOOL IsSquareTexturesOnly()
        { return d3dDevDesc.dpcTriCaps.dwTextureCaps &
              D3DPTEXTURECAPS_SQUAREONLY; }

    /**
     * This method invalidates the java-level D3DContext object if
     * the passed DDrawSurface is the current render target.
     * The invalidation needs to be done so that the D3DContext object
     * resets itself in case the native d3d device has been recreated, or
     * the target surface has been lost (in which case this method is called
     * from D3DSD_RestoreSurface function, see D3DSD_RestoreSurface for
     * more info).
     */
    void InvalidateIfTarget(JNIEnv *env, DDrawSurface *lpSurface);

    // primitives batching-related methods
    /**
     * Calls devices's BeginScene if there weren't one already pending,
     * sets the pending flag.
     */
    HRESULT /*NOLOCK*/ BeginScene(jbyte newState);
    /**
     * Only calls device's EndScene if ddResult is an error.
     */
    HRESULT /*NOLOCK*/ EndScene(HRESULT ddResult);
    /**
     * forces the end of batching by calling EndScene if
     * there was BeginScene pending.
     */
    HRESULT /*NOLOCK*/ ForceEndScene();
    /**
     * flushes the queue if the argument is this device's render target
     */
    void    FlushD3DQueueForTarget(DDrawSurface *ddSurface);

    // fields replicating D3DContext class' fields
    jint       compState;
    jfloat     extraAlpha;
    jint       colorPixel;

    // pixel for vertices used in blits via texture mapping,
    // set in SetAlphaComposite()
    jint       blitPolygonPixel;

    /**
     * Current operation state.
     * See STATE_* macros above.
     */
    jbyte      opState;

private:
    D3DContext(DDraw *ddObject, DXObject* dxObject);
    HRESULT InitD3DDevice(IDirect3DDevice7 *d3dDevice);
    /**
     * This method releases an old device, creates a new one,
     * runs d3d caps tests on it and sets the device caps according
     * to the results.
     */
    HRESULT /*NOLOCK*/ CreateAndTestD3DDevice(DxCapabilities *dxCaps);
    HRESULT /*NOLOCK*/ InitMaskTileTexture();
    void    /*NOLOCK*/ UpdateState(jbyte newState);

    IDirect3DDevice7        *d3dDevice;
    IDirect3D7              *d3dObject;
    DDraw                   *ddObject;
    DXObject                *dxObject;
    const GUID              *pDeviceGUID;
    DDrawSurface            *ddTargetSurface;
    DXSurface               *lpMaskTexture;
    DXSurface               *lpGlyphCacheTexture;
    D3DTextureTable         textureTable;
    DDPIXELFORMAT           depthBufferFormat;
    DDPIXELFORMAT           maskTileTexFormat;
    GlyphCacheInfo          *glyphCache;
    BOOL                    glyphCacheAvailable;
    // array of the textures currently set to the device
    IDirectDrawSurface7     *lastTexture[MAX_USED_TEXTURE_STAGE+1];

    /**
     * A weak reference to the java-level D3DContext object.
     * Used to invalidate the java D3DContext object if the device has been
     * recreated.
     * See SetJavaContext() method.
     */
    jobject jD3DContext;

    D3DDEVICEDESC7 d3dDevDesc;
    int deviceCaps;
    BOOL bIsHWRasterizer;

    /**
     * Used to implement simple primitive batching.
     * See BeginScene/EndScene/ForceEndScene.
     */
    BOOL    bBeginScenePending;
#ifdef DEBUG
    int endSceneQueueDepth;
#endif /* DEBUG */

    CriticalSection deviceLock;
};

// - Various vertex formats -------------------------------------------

#define D3DFVF_J2DLVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
typedef struct _J2DLVERTEX {
    float x, y, z;
    DWORD color;
    float tu, tv;
} J2DLVERTEX;

/**
 * We're still debating whether to use a single vertex format
 * for all primitives or specific per-primitive formats.
 * Using different vertex formats reduces the amount of
 * data being sent to the video board, and this shows
 * benetits when running Java2D benchmarks.
 *
 * However, in a typical Swing application the number
 * of primitives of the same type rendered in a row is
 * relatively small, which means that the driver has
 * to spend more time state switching to account for different
 * vertex formats (and according to MSDN, switching vertex format
 * is a very expensive operation). So for this kind of application
 * it's better to stick with a single vertex format.
 */
#define USE_SINGLE_VERTEX_FORMAT

#ifndef USE_SINGLE_VERTEX_FORMAT

#define D3DFVF_J2D_XY_C (D3DFVF_XYZ | D3DFVF_DIFFUSE)
#define D3DFVF_XY_VERTEX D3DFVF_XYZ

typedef struct _J2D_XY_C_VERTEX {
    float x, y, z;
    DWORD color;
} J2D_XY_C_VERTEX;
typedef struct _J2D_XY_VERTEX {
    float x, y, z;
} J2D_XY_VERTEX;

#else // USE_SINGLE_VERTEX_FORMAT

// When using a single vertex format, define
// every format as J2DLVERTEX

#define D3DFVF_J2D_XY_C D3DFVF_J2DLVERTEX
#define D3DFVF_XY_VERTEX D3DFVF_J2DLVERTEX
typedef J2DLVERTEX J2D_XY_C_VERTEX;
typedef J2DLVERTEX J2D_XY_VERTEX;

#endif // USE_SINGLE_VERTEX_FORMAT

typedef J2DLVERTEX      J2DLV_QUAD[4];
typedef J2DLVERTEX      J2DLV_HEXA[6];
typedef J2D_XY_C_VERTEX J2DXYC_HEXA[6];
typedef J2D_XY_VERTEX   J2DXY_HEXA[6];
#define MAX_CACHED_SPAN_VX_NUM 100

// - Helper Macros ---------------------------------------------------

#define D3D_DEPTH_IDX(DEPTH) \
  (((DEPTH) <= 16) ? DEPTH16_IDX : \
    (((DEPTH) <= 24) ? DEPTH24_IDX : DEPTH32_IDX))

#define D3D_TR_IDX(TRAN) ((TRAN) - 1)

#define D3DSD_MASK_TILE_SIZE 32
#define D3D_GCACHE_WIDTH 512
#define D3D_GCACHE_HEIGHT 512
#define D3D_GCACHE_CELL_WIDTH 16
#define D3D_GCACHE_CELL_HEIGHT 16

#define D3DC_NO_CONTEXT_FLAGS \
    sun_java2d_d3d_D3DContext_NO_CONTEXT_FLAGS
#define D3DC_SRC_IS_OPAQUE    \
    sun_java2d_d3d_D3DContext_SRC_IS_OPAQUE

#define J2D_D3D_FAILURE \
    sun_java2d_d3d_D3DContext_J2D_D3D_FAILURE
#define J2D_D3D_PLAIN_SURFACE_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_PLAIN_SURFACE_OK
#define J2D_D3D_OP_TEXTURE_SURFACE_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_OP_TEXTURE_SURFACE_OK
#define J2D_D3D_BM_TEXTURE_SURFACE_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_BM_TEXTURE_SURFACE_OK
#define J2D_D3D_TR_TEXTURE_SURFACE_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_TR_TEXTURE_SURFACE_OK
#define J2D_D3D_DEPTH_SURFACE_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_DEPTH_SURFACE_OK
#define J2D_D3D_OP_RTT_SURFACE_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_OP_RTT_SURFACE_OK
#define J2D_D3D_LINES_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_LINES_OK
#define J2D_D3D_TEXTURE_BLIT_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_TEXTURE_BLIT_OK
#define J2D_D3D_TEXTURE_TRANSFORM_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_TEXTURE_TRANSFORM_OK
#define J2D_D3D_LINE_CLIPPING_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_LINE_CLIPPING_OK
#define J2D_D3D_DEVICE_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_DEVICE_OK
#define J2D_D3D_PIXEL_FORMATS_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_PIXEL_FORMATS_OK
#define J2D_D3D_SET_TRANSFORM_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_SET_TRANSFORM_OK
#define J2D_D3D_HW_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_HW_OK
#define J2D_D3D_ENABLED_OK \
    sun_java2d_d3d_D3DContext_J2D_D3D_ENABLED_OK

#endif D3DCONTEXT_H