aboutsummaryrefslogtreecommitdiff
path: root/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java
blob: 2dd7a183b955621bbb97388354fe86a8fea7e94c (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
447
448
449
450
451
452
453
454
455
456
457
/*
 * Copyright 2005-2007 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.
 */

package sun.java2d.d3d;

import java.awt.AlphaComposite;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import sun.awt.SunHints;
import sun.awt.Win32GraphicsConfig;
import sun.awt.Win32GraphicsDevice;
import sun.awt.image.SurfaceManager;
import sun.java2d.InvalidPipeException;
import sun.java2d.SunGraphics2D;
import sun.java2d.SurfaceData;
import sun.java2d.SurfaceDataProxy;
import sun.java2d.loops.GraphicsPrimitive;
import sun.java2d.loops.SurfaceType;
import sun.java2d.pipe.PixelToShapeConverter;
import sun.java2d.pipe.TextPipe;
import sun.java2d.windows.Win32OffScreenSurfaceData;
import sun.java2d.windows.Win32SurfaceData;
import sun.java2d.windows.WinVolatileSurfaceManager;
import sun.java2d.windows.WindowsFlags;

import static sun.java2d.windows.Win32SurfaceData.*;

public class D3DSurfaceData extends Win32OffScreenSurfaceData {

    // properties of a surface
    /**
     * This property is used for a back-buffer surface
     */
    public static final int D3D_ATTACHED_SURFACE = (1 << 15);
    /**
     * A surface with this property can be used as a Direct3D rendering
     * destination.
     */
    public static final int D3D_RENDER_TARGET    = (1 << 16);

    public static final int
        D3D_INVALID_SURFACE    = 0;
    /**
     * Surface is a Direct3D plain surface (not a texture).
     * Plain surface can be used as render target.
     * VolatileImages typically use plain surfaces as their hardware
     * accelerated surfaces.
     */
    public static final int
        D3D_PLAIN_SURFACE      = (1 << 0) | D3D_RENDER_TARGET;
    /**
     * Direct3D texture. Mostly used for cached accelerated surfaces.
     * Surfaces of this type can be copied from using hardware acceleration
     * by using texture mapping.
     */
    public static final int
        D3D_TEXTURE_SURFACE    = (1 << 1);
    /**
     * Direct3D Backbuffer surface - an attached surface. Used for
     * multibuffered BufferStrategies.
     */
    public static final int
        D3D_BACKBUFFER_SURFACE = D3D_PLAIN_SURFACE | D3D_ATTACHED_SURFACE;
    /**
     * Render-to-texture. A texture which can also be a render target.
     * Combines the benefits of textures (fast copies-from) and
     * backbuffers or plain surfaces (hw-accelerated rendering to the surface)
     */
    public static final int
        D3D_RTT_SURFACE        = D3D_TEXTURE_SURFACE | D3D_RENDER_TARGET;

    // supported texture pixel formats
    public static final int PF_INVALID         =  0;
    public static final int PF_INT_ARGB        =  1;
    public static final int PF_INT_RGB         =  2;
    public static final int PF_INT_RGBX        =  3;
    public static final int PF_INT_BGR         =  4;
    public static final int PF_USHORT_565_RGB  =  5;
    public static final int PF_USHORT_555_RGB  =  6;
    public static final int PF_USHORT_555_RGBX =  7;
    public static final int PF_INT_ARGB_PRE    =  8;
    public static final int PF_USHORT_4444_ARGB=  9;

    public static final String
        DESC_INT_ARGB_D3D         = "Integer ARGB D3D with translucency";
    public static final String
        DESC_USHORT_4444_ARGB_D3D = "UShort 4444 ARGB D3D with translucency";

    /**
     * Surface type for texture destination.  We cannot render textures to
     * the screen because Direct3D is not clipped by the window's clip list,
     * so we only enable the texture blit loops for copies to offscreen
     * accelerated surfaces.
     */
    public static final String
        DESC_DEST_D3D           = "D3D render target";

    public static final SurfaceType D3DSurface =
        SurfaceType.Any.deriveSubType("Direct3D Surface");
    public static final SurfaceType D3DTexture =
        D3DSurface.deriveSubType("Direct3D Texture");

    /**
     * D3D destination surface types (derive from offscreen dd surfaces).
     * Note that all of these surfaces have the same surface description;
     * we do not care about the depth of the surface since texture ops
     * support multiple depths.
     */
    public static final SurfaceType IntRgbD3D =
        IntRgbDD.deriveSubType(DESC_DEST_D3D);

    public static final SurfaceType IntRgbxD3D =
        IntRgbxDD.deriveSubType(DESC_DEST_D3D);

    public static final SurfaceType Ushort565RgbD3D =
        Ushort565RgbDD.deriveSubType(DESC_DEST_D3D);

    public static final SurfaceType Ushort555RgbxD3D =
        Ushort555RgbxDD.deriveSubType(DESC_DEST_D3D);

    public static final SurfaceType Ushort555RgbD3D =
        Ushort555RgbDD.deriveSubType(DESC_DEST_D3D);

    // REMIND: Is it possible to have d3d accelerated on this type of surface?
    public static final SurfaceType ThreeByteBgrD3D =
        ThreeByteBgrDD.deriveSubType(DESC_DEST_D3D);

    public static final SurfaceType IntArgbD3D =
        SurfaceType.IntArgb.deriveSubType(DESC_INT_ARGB_D3D);

    public static final SurfaceType Ushort4444ArgbD3D =
        SurfaceType.Ushort4444Argb.deriveSubType(DESC_USHORT_4444_ARGB_D3D);

    // Textures we can render to using d3d
    public static final SurfaceType IntRgbD3D_RTT =
        IntRgbD3D.deriveSubType(DESC_DEST_D3D);

    public static final SurfaceType IntRgbxD3D_RTT =
        IntRgbxD3D.deriveSubType(DESC_DEST_D3D);

    public static final SurfaceType Ushort565RgbD3D_RTT =
        Ushort565RgbD3D.deriveSubType(DESC_DEST_D3D);

    public static final SurfaceType Ushort555RgbxD3D_RTT =
        Ushort555RgbxD3D.deriveSubType(DESC_DEST_D3D);

    public static final SurfaceType Ushort555RgbD3D_RTT =
        Ushort555RgbD3D.deriveSubType(DESC_DEST_D3D);

    public static final SurfaceType Ushort4444ArgbD3D_RTT =
        Ushort4444ArgbD3D.deriveSubType(DESC_DEST_D3D);

    public static final SurfaceType IntArgbD3D_RTT =
        IntArgbD3D.deriveSubType(DESC_DEST_D3D);

    public static final SurfaceType ThreeByteBgrD3D_RTT =
        ThreeByteBgrD3D.deriveSubType(DESC_DEST_D3D);

    // the type of this surface - texture, plain, back-buffer
    protected int type;
    protected int pixelFormat;

    private D3DContext d3dContext;

    protected static D3DRenderer d3dPipe;
    protected static PixelToShapeConverter d3dTxPipe;
    protected static D3DTextRenderer d3dTextPipe;
    protected static D3DDrawImage d3dDrawImagePipe;

    private native void initOps(int depth, int transparency);

    static {
        if (WindowsFlags.isD3DEnabled()) {
            D3DBlitLoops.register();
            D3DMaskFill.register();
        }

        d3dPipe = new D3DRenderer();
        d3dTxPipe = new PixelToShapeConverter(d3dPipe);
        d3dTextPipe = new D3DTextRenderer();
        d3dDrawImagePipe = new D3DDrawImage();

        if (GraphicsPrimitive.tracingEnabled()) {
            d3dPipe = d3dPipe.traceWrapD3D();
            d3dTextPipe = d3dTextPipe.traceWrap();
        }
    }

    @Override
    public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
        //D3D may be eliminated soon so no Proxy was created for it...
        //return D3DSurfaceDataProxy.createProxy(srcData, graphicsConfig);
        return SurfaceDataProxy.UNCACHED;
    }

    /**
     * Non-public constructor.  Use createData() to create an object.
     *
     * This constructor is used to house the common construction
     * code shared between the creation of D3DSurfaceData objects
     * and subclasses of D3DSurfaceData (such as D3DBackBufferSD).
     *
     * It calls the common constructor in the parent, and then
     * initializes other shared D3D data.
     */
    protected D3DSurfaceData(int width, int height,
                             int d3dSurfaceType,
                             SurfaceType sType, ColorModel cm,
                             GraphicsConfiguration gc,
                             Image image, int transparency)
    {
        super(width, height, sType, cm, gc, image, transparency);
        this.type = d3dSurfaceType;
    }

    /**
     * Private constructor.  Use createData() to create an object.
     *
     * This constructor calls the common constructor above and then
     * performs the specific initialization of the D3DSurface.
     */
    private D3DSurfaceData(int width, int height,
                           int d3dSurfaceType,
                           SurfaceType sType, ColorModel cm,
                           GraphicsConfiguration gc,
                           Image image, int transparency,
                           int screen)
    {
        this(width, height, d3dSurfaceType, sType, cm, gc, image, transparency);
        pixelFormat = initSurface(width, height, screen,
                                  null /*parent SurfaceData*/);
    }

    public static D3DSurfaceData createData(int width, int height,
                                            int d3dSurfaceType,
                                            ColorModel cm,
                                            GraphicsConfiguration gc,
                                            Image image)
    {
        Win32GraphicsDevice gd = (Win32GraphicsDevice)gc.getDevice();
        // After a display change ddInstance may not be
        // recreated yet, and in this case isD3DEnabledOnDevice will
        // return false, until someone attempted to recreate the
        // primary.
        if (!gd.isD3DEnabledOnDevice()) {
            return null;
        }

        return new D3DSurfaceData(width, height,
                                  d3dSurfaceType,
                                  getSurfaceType(gc, cm, d3dSurfaceType),
                                  cm, gc, image,
                                  cm.getTransparency(), gd.getScreen());
    }

    int getPixelFormat() {
        return pixelFormat;
    }

    static SurfaceType getSurfaceType(GraphicsConfiguration gc,
                                      ColorModel cm,
                                      int d3dSurfaceType)
    {
        if (d3dSurfaceType == D3D_TEXTURE_SURFACE) {
            // for non-rtt textures we have only one surface type
            return D3DTexture;
        } else {
            int pixelSize = cm.getPixelSize();
            Win32GraphicsDevice gd = (Win32GraphicsDevice)gc.getDevice();
            int transparency = cm.getTransparency();

            // We'll attempt to use render-to-texture if render target is
            // requested, but it's not a back-buffer and we support RTT
            // for this configuration.
            boolean useRTT =
                ((d3dSurfaceType & D3D_RENDER_TARGET) != 0) &&
                ((d3dSurfaceType & D3D_BACKBUFFER_SURFACE) == 0) &&
                gd.getD3DContext().isRTTSupported();

            // if there's no RTT available, we can't accelerate non-opaque
            // surfaces, so we return null.
            if (transparency == Transparency.TRANSLUCENT ||
                transparency == Transparency.BITMASK)
            {
                if (pixelSize == 16) {
                    return useRTT ? Ushort4444ArgbD3D_RTT :
                        null/*Ushort4444ArgbD3D*/;
                } else {
                    return useRTT ? IntArgbD3D_RTT : null/*IntArgbD3D*/;
                }
            } else {
                // it's an opaque surface, either a VI or a back-buffer
                switch (pixelSize) {
                case 32:
                case 24:
                    if (cm instanceof DirectColorModel) {
                        if (((DirectColorModel)cm).getRedMask() == 0xff0000) {
                            return useRTT ? IntRgbD3D_RTT : IntRgbD3D;
                        } else {
                            return useRTT ? IntRgbxD3D_RTT : IntRgbxD3D;
                        }
                    } else {
                        return useRTT ? ThreeByteBgrD3D_RTT : ThreeByteBgrD3D;
                    }
                case 15:
                    return useRTT ? Ushort555RgbD3D_RTT : Ushort555RgbD3D;
                case 16:
                    if ((cm instanceof DirectColorModel) &&
                        (((DirectColorModel)cm).getBlueMask() == 0x3e))
                    {
                        return useRTT ? Ushort555RgbxD3D_RTT : Ushort555RgbxD3D;
                    } else {
                        return useRTT ? Ushort565RgbD3D_RTT : Ushort565RgbD3D;
                    }
                case 8: // not supported
                default:
                    throw new sun.java2d.InvalidPipeException("Unsupported bit " +
                                                              "depth: " +
                                                              cm.getPixelSize());
                }
            }
        }
    }

    private native int initOffScreenSurface(long pCtx,
                                            long pData, long parentPdata,
                                            int width, int height,
                                            int type, int screen);

    protected int initSurface(int width, int height, int screen,
                              Win32SurfaceData parentData)
    {
        int pFormat = PF_INVALID;

        synchronized (D3DContext.LOCK) {
            long pData = getNativeOps();
            long pDataParent = 0L;
            if (parentData != null) {
                pDataParent = parentData.getNativeOps();
            }
            D3DContext d3dContext = getContext();
            long pCtx = d3dContext.getNativeContext();
            // native context could be 0 if the context is currently invalid,
            // so attempt to revalidate
            if (pCtx == 0) {
                d3dContext.reinitNativeContext();
                pCtx = d3dContext.getNativeContext();
            }
            if (pData != 0 && pCtx != 0) {
                pFormat = initOffScreenSurface(pCtx,
                                               pData, pDataParent,
                                               width, height, type, screen);
            } else {
                // if the context can't be restored, give up for now.
                throw new InvalidPipeException("D3DSD.initSurface: pData " +
                                               "or pCtx is null");
            }
        }
        return pFormat;
    }

    @Override
    public void validatePipe(SunGraphics2D sg2d) {
        // we don't support COMP_XOR yet..
        if (sg2d.compositeState < sg2d.COMP_XOR) {
            TextPipe textpipe;
            boolean validated = false;

            if (((sg2d.compositeState <= sg2d.COMP_ISCOPY &&
                  sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) ||
                 (sg2d.compositeState == sg2d.COMP_ALPHA &&
                  sg2d.paintState <= sg2d.PAINT_ALPHACOLOR &&
                  (((AlphaComposite)sg2d.composite).getRule() ==
                   AlphaComposite.SRC_OVER))) &&
                sg2d.textAntialiasHint <= SunHints.INTVAL_TEXT_ANTIALIAS_GASP)
            {
                // D3DTextRenderer handles both AA and non-AA text, but
                // only works if composite is SrcNoEa or SrcOver
                textpipe = d3dTextPipe;
            } else {
                // do this to initialize textpipe correctly; we will attempt
                // to override the non-text pipes below
                super.validatePipe(sg2d);
                textpipe = sg2d.textpipe;
                validated = true;
            }

            if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON &&
                sg2d.paintState <= sg2d.PAINT_ALPHACOLOR)
            {
                sg2d.drawpipe =
                    sg2d.strokeState == sg2d.STROKE_THIN ? d3dPipe : d3dTxPipe;
                sg2d.fillpipe = d3dPipe;
                sg2d.shapepipe = d3dPipe;
            } else if (!validated) {
                super.validatePipe(sg2d);
            }
            // install the text pipe based on our earlier decision
            sg2d.textpipe = textpipe;
        } else {
            super.validatePipe(sg2d);
        }

        // always override the image pipe with the specialized D3D pipe
        sg2d.imagepipe = d3dDrawImagePipe;
    }

    /**
     * Disables D3D acceleration on the surface manager of this surfaceData
     * object. This can happen when we encounter a hard error in rendering a D3D
     * primitive (for example, if we were unable to set a surface as D3D target
     * surface).
     * Upon next validation the SurfaceManager will create a non-D3D surface.
     */
    public void disableD3D() {
        markSurfaceLost();
        SurfaceManager sMgr = SurfaceManager.getManager(image);
        if (sMgr instanceof WinVolatileSurfaceManager) {
            ((WinVolatileSurfaceManager)sMgr).setD3DAccelerationEnabled(false);
        }
    }

    @Override
    public boolean surfacePunted() {
        // Punting is disabled for D3D surfaces
        return false;
    }

    D3DContext getContext() {
        return ((Win32GraphicsDevice)graphicsConfig.getDevice()).getD3DContext();
    }
}