aboutsummaryrefslogtreecommitdiff
path: root/src/windows/native/sun/java2d/d3d/D3DRenderQueue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/windows/native/sun/java2d/d3d/D3DRenderQueue.cpp')
-rw-r--r--src/windows/native/sun/java2d/d3d/D3DRenderQueue.cpp954
1 files changed, 954 insertions, 0 deletions
diff --git a/src/windows/native/sun/java2d/d3d/D3DRenderQueue.cpp b/src/windows/native/sun/java2d/d3d/D3DRenderQueue.cpp
new file mode 100644
index 000000000..e33f1c4e1
--- /dev/null
+++ b/src/windows/native/sun/java2d/d3d/D3DRenderQueue.cpp
@@ -0,0 +1,954 @@
+/*
+ * Copyright 2007-2008 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.
+ */
+
+#include <malloc.h>
+#include <jni.h>
+#include "sun_java2d_pipe_BufferedOpCodes.h"
+
+#include "jlong.h"
+#include "D3DBlitLoops.h"
+#include "D3DBufImgOps.h"
+#include "D3DPipelineManager.h"
+#include "D3DContext.h"
+#include "D3DMaskBlit.h"
+#include "D3DMaskFill.h"
+#include "D3DPaints.h"
+#include "D3DRenderQueue.h"
+#include "D3DRenderer.h"
+#include "D3DSurfaceData.h"
+#include "D3DTextRenderer.h"
+#include "Trace.h"
+#include "awt_Toolkit.h"
+
+BOOL DWMIsCompositionEnabled();
+
+/**
+ * References to the "current" context and destination surface.
+ */
+static D3DContext *d3dc = NULL;
+static D3DSDOps *dstOps = NULL;
+static BOOL bLostDevices = FALSE;
+
+typedef struct {
+ byte *buffer;
+ int limit;
+ jobject runnable;
+} FlushBufferStruct;
+
+HRESULT
+D3DRQ_SwapBuffers(D3DPipelineManager *pMgr, D3DSDOps *d3dsdo,
+ int x1, int y1, int x2, int y2)
+{
+ HRESULT res;
+ D3DContext *pCtx;
+ IDirect3DSwapChain9 *pSwapChain;
+ RECT srcRect, dstRect, *pSrcRect, *pDstRect;
+
+ J2dTraceLn(J2D_TRACE_INFO, "D3DRQ_SwapBuffers");
+ J2dTraceLn4(J2D_TRACE_VERBOSE, " x1=%d y1=%d x2=%d y2=%d",
+ x1, y1, x2, y2);
+
+ RETURN_STATUS_IF_NULL(d3dsdo, E_FAIL);
+ RETURN_STATUS_IF_NULL(d3dsdo->pResource, E_FAIL);
+ RETURN_STATUS_IF_NULL(pSwapChain=d3dsdo->pResource->GetSwapChain(), E_FAIL);
+
+ pCtx = D3DRQ_GetCurrentContext();
+ if (pCtx != NULL) {
+ // flush the current vertex queue here, just in case
+ res = d3dc->FlushVertexQueue();
+ D3DRQ_MarkLostIfNeeded(res, dstOps);
+ pCtx = NULL;
+ }
+ // end scene for this destination
+ res = pMgr->GetD3DContext(d3dsdo->adapter, &pCtx);
+ RETURN_STATUS_IF_FAILED(res);
+
+ pCtx->EndScene();
+
+ // This is a workaround for what apparently is a DWM bug.
+ // If the dimensions of the back-buffer don't match the dimensions of
+ // the window, Present() will flash the whole window with black.
+ // The workaround is to detect this situation and not do a present.
+ // It is ok to do so since a repaint event is coming due to the resize that
+ // just happened.
+ //
+ // REMIND: this will need to be updated if we switch to creating
+ // back-buffers of the size of the client area instead of the whole window
+ // (use GetClientRect() instead of GetWindowRect()).
+ if (DWMIsCompositionEnabled()) {
+ RECT r;
+ D3DPRESENT_PARAMETERS params;
+
+ pSwapChain->GetPresentParameters(&params);
+ GetWindowRect(params.hDeviceWindow, &r);
+ int ww = r.right - r.left;
+ int wh = r.bottom - r.top;
+ if (ww != params.BackBufferWidth || wh != params.BackBufferHeight) {
+ J2dTraceLn4(J2D_TRACE_WARNING,
+ "D3DRQ_SwapBuffers: surface/window dimensions mismatch: "\
+ "win: w=%d h=%d, bb: w=%d h=%d",
+ ww, wh, params.BackBufferWidth, params.BackBufferHeight);
+
+ return S_OK;
+ }
+ }
+
+ if (d3dsdo->swapEffect == D3DSWAPEFFECT_COPY) {
+ J2dTraceLn(J2D_TRACE_VERBOSE, " D3DSWAPEFFECT_COPY");
+ if (x1 < 0) x1 = 0;
+ if (y1 < 0) y1 = 0;
+ if (x2 > d3dsdo->width) x2 = d3dsdo->width;
+ if (y2 > d3dsdo->height) y2 = d3dsdo->height;
+ if (x2 <= x1 || y2 <= y1) {
+ // nothing to present
+ return S_OK;
+ }
+ srcRect.left = x1;
+ srcRect.top = y1;
+ srcRect.right = x2;
+ srcRect.bottom = y2;
+
+ dstRect = srcRect;
+
+ pSrcRect = &srcRect;
+ pDstRect = &dstRect;
+ // only offset in windowed mode
+ if (pCtx!= NULL && pCtx->GetPresentationParams()->Windowed) {
+ OffsetRect(pDstRect, d3dsdo->xoff, d3dsdo->yoff);
+ } else {
+ // some boards (Nvidia) have problems with copy strategy and
+ // non-null src/dest rectangles in fs mode; unfortunately this
+ // means that we'll paint over fs window decorations
+ pSrcRect = NULL;
+ pDstRect = NULL;
+ }
+ } else {
+ if (d3dsdo->swapEffect == D3DSWAPEFFECT_FLIP) {
+ J2dTraceLn(J2D_TRACE_VERBOSE, " D3DSWAPEFFECT_FLIP");
+ } else {
+ J2dTraceLn(J2D_TRACE_VERBOSE, " D3DSWAPEFFECT_DISCARD");
+ }
+ // src and dest rectangles must be NULL for FLIP/DISCARD
+ pSrcRect = NULL;
+ pDstRect = NULL;
+ }
+
+ res = pSwapChain->Present(pSrcRect, pDstRect, 0, NULL, 0);
+ res = D3DRQ_MarkLostIfNeeded(res, d3dsdo);
+
+ return res;
+}
+
+HRESULT
+D3DRQ_MarkLostIfNeeded(HRESULT res, D3DSDOps *d3dops)
+{
+ if (res == D3DERR_DEVICELOST || res == D3DERR_DEVICENOTRESET) {
+ D3DContext *pCtx;
+
+ J2dTraceLn(J2D_TRACE_WARNING, "D3DRQ_MarkLostIfNeeded: device lost");
+ bLostDevices = TRUE;
+
+ // only mark surfaces belonging to the lost device
+ if (d3dops != NULL &&
+ SUCCEEDED(res = D3DPipelineManager::GetInstance()->
+ GetD3DContext(d3dops->adapter, &pCtx)))
+ {
+ IDirect3DDevice9 *pd3dDevice = pCtx->Get3DDevice();
+ if (pd3dDevice) {
+ HRESULT res1 = pd3dDevice->TestCooperativeLevel();
+ if (res1 != D3DERR_DEVICELOST && res1 != D3DERR_DEVICENOTRESET){
+ // this surface's device is not lost, do not mark it
+ return res;
+ }
+ }
+ }
+ D3DSD_MarkLost(d3dops);
+ }
+ return res;
+}
+
+void D3DRQ_FlushBuffer(void *pParam)
+{
+ FlushBufferStruct *pFlush = (FlushBufferStruct*)pParam;
+ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+ unsigned char *b, *end;
+ int limit;
+ HRESULT res = S_OK;
+ BOOL bSync = FALSE;
+
+ b = pFlush->buffer;
+ limit = pFlush->limit;
+ J2dTraceLn1(J2D_TRACE_INFO, "D3DRQ_flushBuffer: limit=%d", limit);
+
+ end = b + limit;
+
+ D3DPipelineManager *pMgr = D3DPipelineManager::GetInstance();
+ if (pMgr == NULL) {
+ J2dRlsTraceLn(J2D_TRACE_WARNING, "D3DRQ_flushBuffer: null manager");
+ return;
+ }
+
+ if (bLostDevices) {
+ if (SUCCEEDED(res = pMgr->HandleLostDevices())) {
+ bLostDevices = FALSE;
+ }
+ }
+
+ while (b < end) {
+ jint opcode = NEXT_INT(b);
+
+ J2dTraceLn1(J2D_TRACE_VERBOSE, "D3DRQ_flushBuffer: opcode=%d", opcode);
+
+ switch (opcode) {
+
+ // draw ops
+ case sun_java2d_pipe_BufferedOpCodes_DRAW_LINE:
+ {
+ jint x1 = NEXT_INT(b);
+ jint y1 = NEXT_INT(b);
+ jint x2 = NEXT_INT(b);
+ jint y2 = NEXT_INT(b);
+
+ CONTINUE_IF_NULL(d3dc);
+ res = D3DRenderer_DrawLine(d3dc, x1, y1, x2, y2);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_DRAW_RECT:
+ {
+ jint x = NEXT_INT(b);
+ jint y = NEXT_INT(b);
+ jint w = NEXT_INT(b);
+ jint h = NEXT_INT(b);
+ CONTINUE_IF_NULL(d3dc);
+ res = D3DRenderer_DrawRect(d3dc, x, y, w, h);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_DRAW_POLY:
+ {
+ jint nPoints = NEXT_INT(b);
+ jboolean isClosed = NEXT_BOOLEAN(b);
+ jint transX = NEXT_INT(b);
+ jint transY = NEXT_INT(b);
+ jint *xPoints = (jint *)b;
+ jint *yPoints = ((jint *)b) + nPoints;
+ CONTINUE_IF_NULL(d3dc);
+ res = D3DRenderer_DrawPoly(d3dc, nPoints, isClosed,
+ transX, transY,
+ xPoints, yPoints);
+ SKIP_BYTES(b, nPoints * BYTES_PER_POLY_POINT);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_DRAW_PIXEL:
+ {
+ jint x = NEXT_INT(b);
+ jint y = NEXT_INT(b);
+
+ CONTINUE_IF_NULL(d3dc);
+ res = D3DRenderer_DrawLine(d3dc, x, y, x, y);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_DRAW_SCANLINES:
+ {
+ jint count = NEXT_INT(b);
+ res = D3DRenderer_DrawScanlines(d3dc, count, (jint *)b);
+ SKIP_BYTES(b, count * BYTES_PER_SCANLINE);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_DRAW_PARALLELOGRAM:
+ {
+ jfloat x11 = NEXT_FLOAT(b);
+ jfloat y11 = NEXT_FLOAT(b);
+ jfloat dx21 = NEXT_FLOAT(b);
+ jfloat dy21 = NEXT_FLOAT(b);
+ jfloat dx12 = NEXT_FLOAT(b);
+ jfloat dy12 = NEXT_FLOAT(b);
+ jfloat lwr21 = NEXT_FLOAT(b);
+ jfloat lwr12 = NEXT_FLOAT(b);
+
+ CONTINUE_IF_NULL(d3dc);
+ res = D3DRenderer_DrawParallelogram(d3dc,
+ x11, y11,
+ dx21, dy21,
+ dx12, dy12,
+ lwr21, lwr12);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_DRAW_AAPARALLELOGRAM:
+ {
+ jfloat x11 = NEXT_FLOAT(b);
+ jfloat y11 = NEXT_FLOAT(b);
+ jfloat dx21 = NEXT_FLOAT(b);
+ jfloat dy21 = NEXT_FLOAT(b);
+ jfloat dx12 = NEXT_FLOAT(b);
+ jfloat dy12 = NEXT_FLOAT(b);
+ jfloat lwr21 = NEXT_FLOAT(b);
+ jfloat lwr12 = NEXT_FLOAT(b);
+
+ CONTINUE_IF_NULL(d3dc);
+ res = D3DRenderer_DrawAAParallelogram(d3dc,
+ x11, y11,
+ dx21, dy21,
+ dx12, dy12,
+ lwr21, lwr12);
+ }
+ break;
+
+ // fill ops
+ case sun_java2d_pipe_BufferedOpCodes_FILL_RECT:
+ {
+ jint x = NEXT_INT(b);
+ jint y = NEXT_INT(b);
+ jint w = NEXT_INT(b);
+ jint h = NEXT_INT(b);
+
+ CONTINUE_IF_NULL(d3dc);
+ res = D3DRenderer_FillRect(d3dc, x, y, w, h);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_FILL_PARALLELOGRAM:
+ {
+ jfloat x11 = NEXT_FLOAT(b);
+ jfloat y11 = NEXT_FLOAT(b);
+ jfloat dx21 = NEXT_FLOAT(b);
+ jfloat dy21 = NEXT_FLOAT(b);
+ jfloat dx12 = NEXT_FLOAT(b);
+ jfloat dy12 = NEXT_FLOAT(b);
+
+ CONTINUE_IF_NULL(d3dc);
+ res = D3DRenderer_FillParallelogram(d3dc,
+ x11, y11,
+ dx21, dy21,
+ dx12, dy12);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_FILL_AAPARALLELOGRAM:
+ {
+ jfloat x11 = NEXT_FLOAT(b);
+ jfloat y11 = NEXT_FLOAT(b);
+ jfloat dx21 = NEXT_FLOAT(b);
+ jfloat dy21 = NEXT_FLOAT(b);
+ jfloat dx12 = NEXT_FLOAT(b);
+ jfloat dy12 = NEXT_FLOAT(b);
+
+ CONTINUE_IF_NULL(d3dc);
+ res = D3DRenderer_FillAAParallelogram(d3dc,
+ x11, y11,
+ dx21, dy21,
+ dx12, dy12);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_FILL_SPANS:
+ {
+ jint count = NEXT_INT(b);
+ res = D3DRenderer_FillSpans(d3dc, count, (jint *)b);
+ SKIP_BYTES(b, count * BYTES_PER_SPAN);
+ }
+ break;
+
+ // text-related ops
+ case sun_java2d_pipe_BufferedOpCodes_DRAW_GLYPH_LIST:
+ {
+ jint numGlyphs = NEXT_INT(b);
+ jint packedParams = NEXT_INT(b);
+ jfloat glyphListOrigX = NEXT_FLOAT(b);
+ jfloat glyphListOrigY = NEXT_FLOAT(b);
+ jboolean usePositions = EXTRACT_BOOLEAN(packedParams,
+ OFFSET_POSITIONS);
+ jboolean subPixPos = EXTRACT_BOOLEAN(packedParams,
+ OFFSET_SUBPIXPOS);
+ jboolean rgbOrder = EXTRACT_BOOLEAN(packedParams,
+ OFFSET_RGBORDER);
+ jint lcdContrast = EXTRACT_BYTE(packedParams,
+ OFFSET_CONTRAST);
+ unsigned char *images = b;
+ unsigned char *positions;
+ jint bytesPerGlyph;
+ if (usePositions) {
+ positions = (b + numGlyphs * BYTES_PER_GLYPH_IMAGE);
+ bytesPerGlyph = BYTES_PER_POSITIONED_GLYPH;
+ } else {
+ positions = NULL;
+ bytesPerGlyph = BYTES_PER_GLYPH_IMAGE;
+ }
+ res = D3DTR_DrawGlyphList(d3dc, dstOps,
+ numGlyphs, usePositions,
+ subPixPos, rgbOrder, lcdContrast,
+ glyphListOrigX, glyphListOrigY,
+ images, positions);
+ SKIP_BYTES(b, numGlyphs * bytesPerGlyph);
+ }
+ break;
+
+ // copy-related ops
+ case sun_java2d_pipe_BufferedOpCodes_COPY_AREA:
+ {
+ jint x = NEXT_INT(b);
+ jint y = NEXT_INT(b);
+ jint w = NEXT_INT(b);
+ jint h = NEXT_INT(b);
+ jint dx = NEXT_INT(b);
+ jint dy = NEXT_INT(b);
+ res = D3DBlitLoops_CopyArea(env, d3dc, dstOps,
+ x, y, w, h, dx, dy);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_BLIT:
+ {
+ jint packedParams = NEXT_INT(b);
+ jint sx1 = NEXT_INT(b);
+ jint sy1 = NEXT_INT(b);
+ jint sx2 = NEXT_INT(b);
+ jint sy2 = NEXT_INT(b);
+ jdouble dx1 = NEXT_DOUBLE(b);
+ jdouble dy1 = NEXT_DOUBLE(b);
+ jdouble dx2 = NEXT_DOUBLE(b);
+ jdouble dy2 = NEXT_DOUBLE(b);
+ jlong pSrc = NEXT_LONG(b);
+ jlong pDst = NEXT_LONG(b);
+ jint hint = EXTRACT_BYTE(packedParams, OFFSET_HINT);
+ jboolean texture = EXTRACT_BOOLEAN(packedParams,
+ OFFSET_TEXTURE);
+ jboolean rtt = EXTRACT_BOOLEAN(packedParams,
+ OFFSET_RTT);
+ jboolean xform = EXTRACT_BOOLEAN(packedParams,
+ OFFSET_XFORM);
+ jboolean isoblit = EXTRACT_BOOLEAN(packedParams,
+ OFFSET_ISOBLIT);
+ if (isoblit) {
+ res = D3DBlitLoops_IsoBlit(env, d3dc, pSrc, pDst,
+ xform, hint, texture, rtt,
+ sx1, sy1, sx2, sy2,
+ dx1, dy1, dx2, dy2);
+ D3DRQ_MarkLostIfNeeded(res, (D3DSDOps*)pSrc);
+ } else {
+ jint srctype = EXTRACT_BYTE(packedParams, OFFSET_SRCTYPE);
+ res = D3DBlitLoops_Blit(env, d3dc, pSrc, pDst,
+ xform, hint, srctype, texture,
+ sx1, sy1, sx2, sy2,
+ dx1, dy1, dx2, dy2);
+ }
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_SURFACE_TO_SW_BLIT:
+ {
+ jint sx = NEXT_INT(b);
+ jint sy = NEXT_INT(b);
+ jint dx = NEXT_INT(b);
+ jint dy = NEXT_INT(b);
+ jint w = NEXT_INT(b);
+ jint h = NEXT_INT(b);
+ jint dsttype = NEXT_INT(b);
+ jlong pSrc = NEXT_LONG(b);
+ jlong pDst = NEXT_LONG(b);
+ res = D3DBlitLoops_SurfaceToSwBlit(env, d3dc,
+ pSrc, pDst, dsttype,
+ sx, sy, dx, dy, w, h);
+ D3DRQ_MarkLostIfNeeded(res, (D3DSDOps*)pSrc);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_MASK_FILL:
+ {
+ jint x = NEXT_INT(b);
+ jint y = NEXT_INT(b);
+ jint w = NEXT_INT(b);
+ jint h = NEXT_INT(b);
+ jint maskoff = NEXT_INT(b);
+ jint maskscan = NEXT_INT(b);
+ jint masklen = NEXT_INT(b);
+ unsigned char *pMask = (masklen > 0) ? b : NULL;
+ res = D3DMaskFill_MaskFill(d3dc, x, y, w, h,
+ maskoff, maskscan, masklen, pMask);
+ SKIP_BYTES(b, masklen);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_MASK_BLIT:
+ {
+ jint dstx = NEXT_INT(b);
+ jint dsty = NEXT_INT(b);
+ jint width = NEXT_INT(b);
+ jint height = NEXT_INT(b);
+ jint masklen = width * height * sizeof(jint);
+ res = D3DMaskBlit_MaskBlit(env, d3dc,
+ dstx, dsty, width, height, b);
+ SKIP_BYTES(b, masklen);
+ }
+ break;
+
+ // state-related ops
+ case sun_java2d_pipe_BufferedOpCodes_SET_RECT_CLIP:
+ {
+ jint x1 = NEXT_INT(b);
+ jint y1 = NEXT_INT(b);
+ jint x2 = NEXT_INT(b);
+ jint y2 = NEXT_INT(b);
+ CONTINUE_IF_NULL(d3dc);
+ res = d3dc->SetRectClip(x1, y1, x2, y2);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_BEGIN_SHAPE_CLIP:
+ {
+ CONTINUE_IF_NULL(d3dc);
+ res = d3dc->BeginShapeClip();
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_SET_SHAPE_CLIP_SPANS:
+ {
+ jint count = NEXT_INT(b);
+ res = D3DRenderer_FillSpans(d3dc, count, (jint *)b);
+ SKIP_BYTES(b, count * BYTES_PER_SPAN);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_END_SHAPE_CLIP:
+ {
+ CONTINUE_IF_NULL(d3dc);
+ res = d3dc->EndShapeClip();
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_RESET_CLIP:
+ {
+ CONTINUE_IF_NULL(d3dc);
+ res = d3dc->ResetClip();
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_SET_ALPHA_COMPOSITE:
+ {
+ jint rule = NEXT_INT(b);
+ jfloat extraAlpha = NEXT_FLOAT(b);
+ jint flags = NEXT_INT(b);
+ CONTINUE_IF_NULL(d3dc);
+ res = d3dc->SetAlphaComposite(rule, extraAlpha, flags);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_SET_XOR_COMPOSITE:
+ {
+ jint xorPixel = NEXT_INT(b);
+// res = d3dc->SetXorComposite(d3dc, xorPixel);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_RESET_COMPOSITE:
+ {
+ CONTINUE_IF_NULL(d3dc);
+ res = d3dc->ResetComposite();
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_SET_TRANSFORM:
+ {
+ jdouble m00 = NEXT_DOUBLE(b);
+ jdouble m10 = NEXT_DOUBLE(b);
+ jdouble m01 = NEXT_DOUBLE(b);
+ jdouble m11 = NEXT_DOUBLE(b);
+ jdouble m02 = NEXT_DOUBLE(b);
+ jdouble m12 = NEXT_DOUBLE(b);
+ res = d3dc->SetTransform(m00, m10, m01, m11, m02, m12);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_RESET_TRANSFORM:
+ {
+ CONTINUE_IF_NULL(d3dc);
+ res = d3dc->ResetTransform();
+ }
+ break;
+
+ // context-related ops
+ case sun_java2d_pipe_BufferedOpCodes_SET_SURFACES:
+ {
+ jlong pSrc = NEXT_LONG(b);
+ jlong pDst = NEXT_LONG(b);
+ D3DContext *oldd3dc = NULL;
+ if (d3dc != NULL) {
+ oldd3dc = d3dc;
+ d3dc = NULL;
+ oldd3dc->UpdateState(STATE_CHANGE);
+ }
+ dstOps = (D3DSDOps *)jlong_to_ptr(pDst);
+ res = pMgr->GetD3DContext(dstOps->adapter, &d3dc);
+ if (FAILED(res)) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "D3DRQ_FlushBuffer: failed to get context");
+ D3DRQ_ResetCurrentContextAndDestination();
+ break;
+ }
+ // REMIND: we may also want to do EndScene on each
+ // render target change so that the GPU can go work on
+ // whatever is already in the queue
+ if (oldd3dc != d3dc && oldd3dc != NULL) {
+ res = oldd3dc->EndScene();
+ }
+ CONTINUE_IF_NULL(dstOps->pResource);
+ res = d3dc->SetRenderTarget(dstOps->pResource->GetSurface());
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_SET_SCRATCH_SURFACE:
+ {
+ jint screen = NEXT_INT(b);
+ jint adapter = pMgr->GetAdapterOrdinalForScreen(screen);
+ D3DContext *oldd3dc = NULL;
+
+ if (d3dc != NULL) {
+ oldd3dc = d3dc;
+ d3dc = NULL;
+ }
+ res = pMgr->GetD3DContext(adapter, &d3dc);
+ if (FAILED(res)) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "D3DRQ_FlushBuffer: failed to get context");
+ D3DRQ_ResetCurrentContextAndDestination();
+ } else if (oldd3dc != d3dc && oldd3dc != NULL) {
+ res = oldd3dc->EndScene();
+ }
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_FLUSH_SURFACE:
+ {
+ jlong pData = NEXT_LONG(b);
+ D3DSDOps *d3dsdo = (D3DSDOps *)jlong_to_ptr(pData);
+ D3DSD_Flush(d3dsdo);
+ if (dstOps == d3dsdo) {
+ dstOps = NULL;
+ }
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_DISPOSE_SURFACE:
+ {
+ jlong pData = NEXT_LONG(b);
+ D3DSDOps *d3dsdo = (D3DSDOps *)jlong_to_ptr(pData);
+ D3DSD_Flush(d3dsdo);
+ if (dstOps == d3dsdo) {
+ dstOps = NULL;
+ }
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_DISPOSE_CONFIG:
+ {
+ jlong pConfigInfo = NEXT_LONG(b);
+ CONTINUE_IF_NULL(d3dc);
+ // REMIND: does this need to be implemented for D3D?
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_INVALIDATE_CONTEXT:
+ {
+ // flush just in case there are any pending operations in
+ // the hardware pipe
+ if (d3dc != NULL) {
+ res = d3dc->EndScene();
+ }
+
+ // invalidate the references to the current context and
+ // destination surface that are maintained at the native level
+ D3DRQ_ResetCurrentContextAndDestination();
+ }
+ break;
+
+ case sun_java2d_pipe_BufferedOpCodes_SYNC:
+ {
+ bSync = TRUE;
+ }
+ break;
+
+ case sun_java2d_pipe_BufferedOpCodes_RESTORE_DEVICES:
+ {
+ J2dTraceLn(J2D_TRACE_INFO, "D3DRQ_FlushBuffer: RESTORE_DEVICES");
+ if (SUCCEEDED(res = pMgr->HandleLostDevices())) {
+ bLostDevices = FALSE;
+ } else {
+ bLostDevices = TRUE;
+ }
+ }
+ break;
+
+ case sun_java2d_pipe_BufferedOpCodes_SAVE_STATE:
+ {
+ CONTINUE_IF_NULL(d3dc);
+
+ res = d3dc->SaveState();
+ }
+ break;
+
+ case sun_java2d_pipe_BufferedOpCodes_RESTORE_STATE:
+ {
+ CONTINUE_IF_NULL(d3dc);
+
+ res = d3dc->RestoreState();
+ }
+ break;
+
+ // multibuffering ops
+ case sun_java2d_pipe_BufferedOpCodes_SWAP_BUFFERS:
+ {
+ jlong sdo = NEXT_LONG(b);
+ jint x1 = NEXT_INT(b);
+ jint y1 = NEXT_INT(b);
+ jint x2 = NEXT_INT(b);
+ jint y2 = NEXT_INT(b);
+
+ res = D3DRQ_SwapBuffers(pMgr, (D3DSDOps *)jlong_to_ptr(sdo),
+ x1, y1, x2, y2);
+ }
+ break;
+
+ // special no-op (mainly used for achieving 8-byte alignment)
+ case sun_java2d_pipe_BufferedOpCodes_NOOP:
+ break;
+
+ // paint-related ops
+ case sun_java2d_pipe_BufferedOpCodes_RESET_PAINT:
+ {
+ res = D3DPaints_ResetPaint(d3dc);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_SET_COLOR:
+ {
+ jint pixel = NEXT_INT(b);
+ res = D3DPaints_SetColor(d3dc, pixel);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_SET_GRADIENT_PAINT:
+ {
+ jboolean useMask= NEXT_BOOLEAN(b);
+ jboolean cyclic = NEXT_BOOLEAN(b);
+ jdouble p0 = NEXT_DOUBLE(b);
+ jdouble p1 = NEXT_DOUBLE(b);
+ jdouble p3 = NEXT_DOUBLE(b);
+ jint pixel1 = NEXT_INT(b);
+ jint pixel2 = NEXT_INT(b);
+ res = D3DPaints_SetGradientPaint(d3dc, useMask, cyclic,
+ p0, p1, p3,
+ pixel1, pixel2);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_SET_LINEAR_GRADIENT_PAINT:
+ {
+ jboolean useMask = NEXT_BOOLEAN(b);
+ jboolean linear = NEXT_BOOLEAN(b);
+ jint cycleMethod = NEXT_INT(b);
+ jint numStops = NEXT_INT(b);
+ jfloat p0 = NEXT_FLOAT(b);
+ jfloat p1 = NEXT_FLOAT(b);
+ jfloat p3 = NEXT_FLOAT(b);
+ void *fractions, *pixels;
+ fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat));
+ pixels = b; SKIP_BYTES(b, numStops * sizeof(jint));
+ res = D3DPaints_SetLinearGradientPaint(d3dc, dstOps,
+ useMask, linear,
+ cycleMethod, numStops,
+ p0, p1, p3,
+ fractions, pixels);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_SET_RADIAL_GRADIENT_PAINT:
+ {
+ jboolean useMask = NEXT_BOOLEAN(b);
+ jboolean linear = NEXT_BOOLEAN(b);
+ jint numStops = NEXT_INT(b);
+ jint cycleMethod = NEXT_INT(b);
+ jfloat m00 = NEXT_FLOAT(b);
+ jfloat m01 = NEXT_FLOAT(b);
+ jfloat m02 = NEXT_FLOAT(b);
+ jfloat m10 = NEXT_FLOAT(b);
+ jfloat m11 = NEXT_FLOAT(b);
+ jfloat m12 = NEXT_FLOAT(b);
+ jfloat focusX = NEXT_FLOAT(b);
+ void *fractions, *pixels;
+ fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat));
+ pixels = b; SKIP_BYTES(b, numStops * sizeof(jint));
+ res = D3DPaints_SetRadialGradientPaint(d3dc, dstOps,
+ useMask, linear,
+ cycleMethod, numStops,
+ m00, m01, m02,
+ m10, m11, m12,
+ focusX,
+ fractions, pixels);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_SET_TEXTURE_PAINT:
+ {
+ jboolean useMask= NEXT_BOOLEAN(b);
+ jboolean filter = NEXT_BOOLEAN(b);
+ jlong pSrc = NEXT_LONG(b);
+ jdouble xp0 = NEXT_DOUBLE(b);
+ jdouble xp1 = NEXT_DOUBLE(b);
+ jdouble xp3 = NEXT_DOUBLE(b);
+ jdouble yp0 = NEXT_DOUBLE(b);
+ jdouble yp1 = NEXT_DOUBLE(b);
+ jdouble yp3 = NEXT_DOUBLE(b);
+ res = D3DPaints_SetTexturePaint(d3dc, useMask, pSrc, filter,
+ xp0, xp1, xp3,
+ yp0, yp1, yp3);
+ }
+ break;
+
+ // BufferedImageOp-related ops
+ case sun_java2d_pipe_BufferedOpCodes_ENABLE_CONVOLVE_OP:
+ {
+ jlong pSrc = NEXT_LONG(b);
+ jboolean edgeZero = NEXT_BOOLEAN(b);
+ jint kernelWidth = NEXT_INT(b);
+ jint kernelHeight = NEXT_INT(b);
+ res = D3DBufImgOps_EnableConvolveOp(d3dc, pSrc, edgeZero,
+ kernelWidth, kernelHeight, b);
+ SKIP_BYTES(b, kernelWidth * kernelHeight * sizeof(jfloat));
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_DISABLE_CONVOLVE_OP:
+ {
+ res = D3DBufImgOps_DisableConvolveOp(d3dc);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_ENABLE_RESCALE_OP:
+ {
+ jlong pSrc = NEXT_LONG(b); // unused
+ jboolean nonPremult = NEXT_BOOLEAN(b);
+ jint numFactors = 4;
+ unsigned char *scaleFactors = b;
+ unsigned char *offsets = (b + numFactors * sizeof(jfloat));
+ res = D3DBufImgOps_EnableRescaleOp(d3dc, nonPremult,
+ scaleFactors, offsets);
+ SKIP_BYTES(b, numFactors * sizeof(jfloat) * 2);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_DISABLE_RESCALE_OP:
+ {
+ D3DBufImgOps_DisableRescaleOp(d3dc);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_ENABLE_LOOKUP_OP:
+ {
+ jlong pSrc = NEXT_LONG(b); // unused
+ jboolean nonPremult = NEXT_BOOLEAN(b);
+ jboolean shortData = NEXT_BOOLEAN(b);
+ jint numBands = NEXT_INT(b);
+ jint bandLength = NEXT_INT(b);
+ jint offset = NEXT_INT(b);
+ jint bytesPerElem = shortData ? sizeof(jshort):sizeof(jbyte);
+ void *tableValues = b;
+ res = D3DBufImgOps_EnableLookupOp(d3dc, nonPremult, shortData,
+ numBands, bandLength, offset,
+ tableValues);
+ SKIP_BYTES(b, numBands * bandLength * bytesPerElem);
+ }
+ break;
+ case sun_java2d_pipe_BufferedOpCodes_DISABLE_LOOKUP_OP:
+ {
+ res = D3DBufImgOps_DisableLookupOp(d3dc);
+ }
+ break;
+
+ default:
+ J2dRlsTraceLn1(J2D_TRACE_ERROR,
+ "D3DRQ_flushBuffer: invalid opcode=%d", opcode);
+ return;
+ }
+ // we may mark the surface lost repeatedly but that won't do much harm
+ res = D3DRQ_MarkLostIfNeeded(res, dstOps);
+ }
+
+ if (d3dc != NULL) {
+ res = d3dc->EndScene();
+ // REMIND: EndScene is not really enough to flush the
+ // whole d3d pipeline
+
+ // REMIND: there may be an issue with BeginScene/EndScene
+ // for each flushQueue, because of the blits, which flush
+ // the queue
+ if (bSync) {
+ res = d3dc->Sync();
+ }
+ }
+
+ // REMIND: we need to also handle hard errors here as well, and disable
+ // particular context if needed
+ D3DRQ_MarkLostIfNeeded(res, dstOps);
+
+ if (!JNU_IsNull(env, pFlush->runnable)) {
+ J2dTraceLn(J2D_TRACE_VERBOSE, " executing runnable");
+ JNU_CallMethodByName(env, NULL, pFlush->runnable, "run", "()V");
+ }
+}
+
+/**
+ * Returns a pointer to the "current" context, as set by the last SET_SURFACES
+ * or SET_SCRATCH_SURFACE operation.
+ */
+D3DContext *
+D3DRQ_GetCurrentContext()
+{
+ return d3dc;
+}
+
+/**
+ * Returns a pointer to the "current" destination surface, as set by the last
+ * SET_SURFACES operation.
+ */
+D3DSDOps *
+D3DRQ_GetCurrentDestination()
+{
+ return dstOps;
+}
+
+/**
+ * Resets current context and destination surface.
+ */
+void
+D3DRQ_ResetCurrentContextAndDestination()
+{
+ J2dTraceLn(J2D_TRACE_INFO, "D3DRQ_ResetCurrentContextAndDestination");
+
+ d3dc = NULL;
+ dstOps = NULL;
+}
+
+extern "C"
+{
+
+/*
+ * Class: sun_java2d_d3d_D3DRenderQueue
+ * Method: flushBuffer
+ * Signature: (JILjava/lang/Runnable;)V
+ */
+JNIEXPORT void JNICALL
+Java_sun_java2d_d3d_D3DRenderQueue_flushBuffer
+ (JNIEnv *env, jobject d3drq, jlong buf, jint limit, jobject runnable)
+{
+ FlushBufferStruct bufstr;
+ // just in case we forget to init any new fields
+ ZeroMemory(&bufstr, sizeof(FlushBufferStruct));
+
+ bufstr.buffer = (unsigned char *)jlong_to_ptr(buf);
+ if (bufstr.buffer == NULL) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "D3DRenderQueue_flushBuffer: cannot get direct buffer address");
+ return;
+ }
+ bufstr.limit = limit;
+
+ bufstr.runnable = JNU_IsNull(env, runnable) ?
+ NULL : env->NewGlobalRef(runnable);
+ AwtToolkit::GetInstance().InvokeFunction(D3DRQ_FlushBuffer, &bufstr);
+ if (!JNU_IsNull(env, bufstr.runnable)) {
+ env->DeleteGlobalRef(bufstr.runnable);
+ }
+}
+
+}