| /* |
| * Copyright (c) 2007, 2008, Oracle and/or its affiliates. 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. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| #include "D3DPipeline.h" |
| #include <malloc.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(¶ms); |
| 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); |
| } |
| } |
| |
| } |