/** * Removes cell info from the glyph's list of cached cells. */ void AccelGlyphCache_RemoveCellInfo(GlyphInfo *glyph, CacheCellInfo *cellInfo) { CacheCellInfo *currCellInfo = glyph->cellInfo; CacheCellInfo *prevInfo = NULL; // assert (glyph!= NULL && glyph->cellInfo != NULL && cellInfo != NULL) J2dTraceLn(J2D_TRACE_INFO, "AccelGlyphCache_RemoveCellInfo"); do { if (currCellInfo == cellInfo) { J2dTraceLn2(J2D_TRACE_VERBOSE, " glyph 0x%x: removing cell 0x%x from glyph's list", glyph, currCellInfo); if (prevInfo == NULL) { // it's the head, chop-chop glyph->cellInfo = currCellInfo->nextGCI; } else { prevInfo->nextGCI = currCellInfo->nextGCI; } currCellInfo->glyphInfo = NULL; currCellInfo->nextGCI = NULL; return; } prevInfo = currCellInfo; currCellInfo = currCellInfo->nextGCI; } while (currCellInfo != NULL); J2dTraceLn2(J2D_TRACE_WARNING, "AccelGlyphCache_RemoveCellInfo: "\ "no cell 0x%x in glyph 0x%x's cell list", cellInfo, glyph); }
// static HRESULT D3DPipelineManager::HandleAdaptersChange(HMONITOR *pHMONITORs, UINT monNum) { HRESULT res = S_OK; BOOL bResetD3D = FALSE, bFound; D3DPipelineManager *pMgr = D3DPipelineManager::GetInstance(); RETURN_STATUS_IF_NULL(pHMONITORs, E_FAIL); if (pMgr == NULL) { // NULL pMgr is valid when the pipeline is not enabled or if it hasn't // been created yet return S_OK; } RETURN_STATUS_IF_NULL(pMgr->pAdapters, E_FAIL); RETURN_STATUS_IF_NULL(pMgr->pd3d9, E_FAIL); J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::HandleAdaptersChange"); if (monNum != pMgr->adapterCount) { J2dTraceLn2(J2D_TRACE_VERBOSE, " number of adapters changed (old=%d, new=%d)", pMgr->adapterCount, monNum); bResetD3D = TRUE; } else { for (UINT i = 0; i < pMgr->adapterCount; i++) { HMONITOR hMon = pMgr->pd3d9->GetAdapterMonitor(i); if (hMon == (HMONITOR)0x0) { J2dTraceLn1(J2D_TRACE_VERBOSE, " adapter %d: removed", i); bResetD3D = TRUE; break; } bFound = FALSE; for (UINT mon = 0; mon < monNum; mon++) { if (pHMONITORs[mon] == hMon) { J2dTraceLn3(J2D_TRACE_VERBOSE, " adapter %d: found hmnd[%d]=0x%x", i, mon, hMon); bFound = TRUE; break; } } if (!bFound) { J2dTraceLn2(J2D_TRACE_VERBOSE, " adapter %d: could not find hmnd=0x%x "\ "in the list of new hmnds", i, hMon); bResetD3D = TRUE; break; } } } if (bResetD3D) { J2dTraceLn(J2D_TRACE_VERBOSE, " adapters changed: resetting d3d"); pMgr->ReleaseD3D(); res = pMgr->InitD3D(); } return res; }
/** * Fetches the OGLContext associated with the given destination surface, * makes the context current for those surfaces, updates the destination * viewport, and then returns a pointer to the OGLContext. */ OGLContext * OGLContext_SetSurfaces(JNIEnv *env, jlong pSrc, jlong pDst) { OGLSDOps *srcOps = (OGLSDOps *)jlong_to_ptr(pSrc); OGLSDOps *dstOps = (OGLSDOps *)jlong_to_ptr(pDst); OGLContext *oglc = NULL; J2dTraceLn(J2D_TRACE_INFO, "OGLContext_SetSurfaces"); if (srcOps == NULL || dstOps == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLContext_SetSurfaces: ops are null"); return NULL; } J2dTraceLn2(J2D_TRACE_VERBOSE, " srctype=%d dsttype=%d", srcOps->drawableType, dstOps->drawableType); if (dstOps->drawableType == OGLSD_TEXTURE) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLContext_SetSurfaces: texture cannot be used as destination"); return NULL; } if (dstOps->drawableType == OGLSD_UNDEFINED) { // initialize the surface as an OGLSD_WINDOW if (!OGLSD_InitOGLWindow(env, dstOps)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLContext_SetSurfaces: could not init OGL window"); return NULL; } } // make the context current oglc = OGLSD_MakeOGLContextCurrent(env, srcOps, dstOps); if (oglc == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLContext_SetSurfaces: could not make context current"); return NULL; } // update the viewport OGLContext_SetViewport(srcOps, dstOps); // perform additional one-time initialization, if necessary if (dstOps->needsInit) { if (dstOps->isOpaque) { // in this case we are treating the destination as opaque, but // to do so, first we need to ensure that the alpha channel // is filled with fully opaque values (see 6319663) OGLContext_InitAlphaChannel(); } dstOps->needsInit = JNI_FALSE; } return oglc; }
// static HRESULT D3DPipelineManager::GDICheckForBadHardware() { DISPLAY_DEVICE dd; dd.cb = sizeof(DISPLAY_DEVICE); int failedDevices = 0; int attachedDevices = 0; int i = 0; WCHAR *id; WCHAR vendorId[5]; WCHAR deviceId[5]; DWORD dwDId, dwVId; J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::GDICheckForBadHardware"); // i<20 is to guard against buggy drivers while (EnumDisplayDevices(NULL, i, &dd, 0) && i < 20) { if (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) { attachedDevices++; id = dd.DeviceID; if (wcslen(id) > 21) { // get vendor ID wcsncpy(vendorId, id+8, 4); int args1 = swscanf(vendorId, L"%X", &dwVId); // get device ID wcsncpy(deviceId, id+17, 4); int args2 = swscanf(deviceId, L"%X", &dwDId); if (args1 == 1 && args2 == 1) { J2dTraceLn2(J2D_TRACE_VERBOSE, " device: vendorID=0x%04x, deviceId=0x%04x", dwVId, dwDId); // since we don't have a driver version here we will // just ask to ignore the version for now; bad hw // entries with specific drivers information will be // processed later when d3d is initialized and we can // obtain a driver version if (FAILED(CheckForBadHardware(dwVId, dwDId, MAX_VERSION))){ failedDevices++; } } } } i++; } if (failedDevices == attachedDevices) { J2dRlsTraceLn(J2D_TRACE_ERROR, "D3DPPLM::GDICheckForBadHardware: no suitable devices found"); return E_FAIL; } return S_OK; }
/* * Class: sun_java2d_windows_GDIRenderer * Method: devCopyArea * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;IIIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_windows_GDIRenderer_devCopyArea (JNIEnv *env, jobject wr, jobject wsd, jint srcx, jint srcy, jint dx, jint dy, jint width, jint height) { GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, wsd); J2dTraceLn(J2D_TRACE_INFO, "GDIWindowSurfaceData_devCopyArea"); J2dTraceLn4(J2D_TRACE_VERBOSE, " srcx=%-4d srcy=%-4d dx=%-4d dy=%-4d", srcx, srcy, dx, dy); J2dTraceLn2(J2D_TRACE_VERBOSE, " w=%-4d h=%-4d", width, height); if (wsdo == NULL) { return; } if (wsdo->invalid) { SurfaceData_ThrowInvalidPipeException(env, "GDIRenderer_devCopyArea: invalid surface data"); return; } HDC hDC = wsdo->GetDC(env, wsdo, 0, NULL, NULL, NULL, 0); if (hDC == NULL) { return; } RECT r; ::SetRect(&r, srcx, srcy, srcx + width, srcy + height); HRGN rgnUpdate = ::CreateRectRgn(0, 0, 0, 0); VERIFY(::ScrollDC(hDC, dx, dy, &r, NULL, rgnUpdate, NULL)); // ScrollDC invalidates the part of the source rectangle that // is outside of the destination rectangle on the assumption // that you wanted to "move" the pixels from source to dest, // and so now you will want to paint new pixels in the source. // Since our copyarea operation involves no such semantics we // are only interested in the part of the update region that // corresponds to unavailable source pixels - i.e. the part // that falls within the destination rectangle. // The update region will be in client relative coordinates // but the destination rect will be in window relative coordinates ::OffsetRect(&r, dx-wsdo->insets.left, dy-wsdo->insets.top); HRGN rgnDst = ::CreateRectRgnIndirect(&r); int result = ::CombineRgn(rgnUpdate, rgnUpdate, rgnDst, RGN_AND); // Invalidate the exposed area. if (result != NULLREGION) { ::InvalidateRgn(wsdo->window, rgnUpdate, TRUE); } ::DeleteObject(rgnUpdate); ::DeleteObject(rgnDst); wsdo->ReleaseDC(env, wsdo, hDC); }
/** * Initializes a framebuffer object, using the given width and height as * a guide. See OGLSD_InitTextureObject() and OGLSD_InitFBObject() * for more information. */ JNIEXPORT jboolean JNICALL Java_sun_java2d_opengl_OGLSurfaceData_initFBObject (JNIEnv *env, jobject oglsd, jlong pData, jboolean isOpaque, jboolean texNonPow2, jboolean texRect, jint width, jint height) { OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); GLuint fbobjectID, depthID; J2dTraceLn2(J2D_TRACE_INFO, "OGLSurfaceData_initFBObject: w=%d h=%d", width, height); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_initFBObject: ops are null"); return JNI_FALSE; } // initialize color texture object if (!OGLSD_InitTextureObject(oglsdo, isOpaque, texNonPow2, texRect, width, height)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_initFBObject: could not init texture object"); return JNI_FALSE; } // initialize framebuffer object using color texture created above if (!OGLSD_InitFBObject(&fbobjectID, &depthID, oglsdo->textureID, oglsdo->textureTarget, oglsdo->textureWidth, oglsdo->textureHeight)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_initFBObject: could not init fbobject"); j2d_glDeleteTextures(1, &oglsdo->textureID); return JNI_FALSE; } oglsdo->drawableType = OGLSD_FBOBJECT; // other fields (e.g. width, height) are set in OGLSD_InitTextureObject() oglsdo->fbobjectID = fbobjectID; oglsdo->depthID = depthID; OGLSD_SetNativeDimensions(env, oglsdo, oglsdo->textureWidth, oglsdo->textureHeight); // framebuffer objects differ from other OpenGL surfaces in that the // value passed to glRead/DrawBuffer() must be GL_COLOR_ATTACHMENTn_EXT, // rather than GL_FRONT (or GL_BACK) oglsdo->activeBuffer = GL_COLOR_ATTACHMENT0_EXT; return JNI_TRUE; }
/* * Class: sun_java2d_windows_GDIRenderer * Method: doFillArc * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_windows_GDIRenderer_doFillArc (JNIEnv *env, jobject wr, jobject sData, jobject clip, jobject comp, jint color, jint x, jint y, jint w, jint h, jint angleStart, jint angleExtent) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doFillArc"); J2dTraceLn5(J2D_TRACE_VERBOSE, " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", color, x, y, w, h); J2dTraceLn2(J2D_TRACE_VERBOSE, " angleStart=%-4d angleExtent=%-4d", angleStart, angleExtent); if (w <= 0 || h <= 0 || angleExtent == 0) { return; } if (angleExtent >= 360 || angleExtent <= -360) { // Fix related to 4411814 - small ovals (and arcs) do not draw // If the arc is a full circle, let the Oval method handle it // since that method can deal with degenerate sizes better. Java_sun_java2d_windows_GDIRenderer_doFillOval(env, wr, sData, clip, comp, color, x, y, w, h); return; } GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData); if (wsdo == NULL) { return; } long sx, sy, ex, ey; int angleEnd; if (angleExtent < 0) { angleEnd = angleStart; angleStart += angleExtent; } else { angleEnd = angleStart + angleExtent; } AngleToCoord(angleStart, w, h, &sx, &sy); sx += x + w/2; sy += y + h/2; AngleToCoord(angleEnd, w, h, &ex, &ey); ex += x + w/2; ey += y + h/2; HDC hdc = wsdo->GetDC(env, wsdo, BRUSHONLY, NULL, clip, comp, color); if (hdc == NULL) { return; } ::Pie(hdc, x, y, x+w+1, y+h+1, sx, sy, ex, ey); wsdo->ReleaseDC(env, wsdo, hdc); }
HWND D3DPipelineManager::SetFSFocusWindow(UINT adapterOrdinal, HWND hWnd) { J2dTraceLn2(J2D_TRACE_INFO,"D3DPPLM::SetFSFocusWindow hwnd=0x%x adapter=%d", hWnd, adapterOrdinal); HWND prev = pAdapters[adapterOrdinal].fsFocusWindow; pAdapters[adapterOrdinal].fsFocusWindow = hWnd; if (currentFSFocusAdapter < 0) { J2dTraceLn(J2D_TRACE_VERBOSE, " first full-screen window"); // first fs window currentFSFocusAdapter = adapterOrdinal; // REMIND: we might want to reset the rest of the context here as well // like we do when the an adapter exits fs mode; currently they will // be reset sometime later } else { // there's already a fs window if (currentFSFocusAdapter == adapterOrdinal) { // it's current fs window => we're exiting fs mode on this adapter; // look for a new fs focus window if (hWnd == 0) { UINT i; currentFSFocusAdapter = -1; for (i = 0; i < adapterCount; i++) { if (pAdapters[i].fsFocusWindow != 0) { J2dTraceLn1(J2D_TRACE_VERBOSE, " adapter %d is still in fs mode", i); currentFSFocusAdapter = i; break; } } // we have to reset all devices any time current focus device // exits fs mode, and also to prevent some of them being left in // a lost state when the last device exits fs - when non-last // adapters exit fs mode they would not be able to create the // device and will be put in a lost state forever HRESULT res; J2dTraceLn(J2D_TRACE_VERBOSE, " adapter exited full-screen, reset all adapters"); for (i = 0; i < adapterCount; i++) { if (pAdapters[i].pd3dContext != NULL) { res = pAdapters[i].pd3dContext->ResetContext(); D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination()); } } } else { J2dTraceLn1(J2D_TRACE_WARNING, "D3DPM::SetFSFocusWindow: setting the fs "\ "window again for adapter %d", adapterOrdinal); } } } return prev; }
void D3DResource::SetSDOps(D3DSDOps *pOps) { if (pOps != NULL && this->pOps != NULL) { // something's wrong, we're overwriting // a non-null field (setting it to null is allowed) J2dTraceLn2(J2D_TRACE_WARNING, "D3DResource::SetSDOps: overwriting "\ "this->pOps=0x%x with pOps=0x%x", this->pOps, pOps); } this->pOps = pOps; }
HWND D3DPipelineManager::CreateDefaultFocusWindow() { UINT adapterOrdinal = D3DADAPTER_DEFAULT; J2dTraceLn1(J2D_TRACE_INFO, "D3DPPLM::CreateDefaultFocusWindow: adapter=%d", adapterOrdinal); if (defaultFocusWindow != 0) { J2dRlsTraceLn(J2D_TRACE_WARNING, "D3DPPLM::CreateDefaultFocusWindow: "\ "existing default focus window!"); return defaultFocusWindow; } WNDCLASS wc; ZeroMemory(&wc, sizeof(WNDCLASS)); wc.hInstance = GetModuleHandle(NULL); wc.lpfnWndProc = DefWindowProc; wc.lpszClassName = L"D3DFocusWindow"; if (RegisterClass(&wc) == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "D3DPPLM::CreateDefaultFocusWindow: "\ "error registering window class"); return 0; } MONITORINFO mi; ZeroMemory(&mi, sizeof(MONITORINFO)); mi.cbSize = sizeof(MONITORINFO); HMONITOR hMon = pd3d9->GetAdapterMonitor(adapterOrdinal); if (hMon == 0 || !GetMonitorInfo(hMon, (LPMONITORINFO)&mi)) { J2dRlsTraceLn1(J2D_TRACE_ERROR, "D3DPPLM::CreateDefaultFocusWindow: "\ "error getting monitor info for adapter=%d", adapterOrdinal); return 0; } HWND hWnd = CreateWindow(L"D3DFocusWindow", L"D3DFocusWindow", 0, mi.rcMonitor.left, mi.rcMonitor.top, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL); if (hWnd == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "D3DPPLM::CreateDefaultFocusWindow: CreateWindow failed"); } else { J2dTraceLn2(J2D_TRACE_INFO, " Created default focus window %x for adapter %d", hWnd, adapterOrdinal); defaultFocusWindow = hWnd; } return hWnd; }
/** * Add cell info to the head of the glyph's list of cached cells. */ void AccelGlyphCache_AddCellInfo(GlyphInfo *glyph, CacheCellInfo *cellInfo) { // assert (glyph != NULL && cellInfo != NULL) J2dTraceLn(J2D_TRACE_INFO, "AccelGlyphCache_AddCellInfo"); J2dTraceLn2(J2D_TRACE_VERBOSE, " glyph 0x%x: adding cell 0x%x to the list", glyph, cellInfo); cellInfo->glyphInfo = glyph; cellInfo->nextGCI = glyph->cellInfo; glyph->cellInfo = cellInfo; glyph->managed = MANAGED_GLYPH; }
/** * Retrieve a pointer to an item in the array and register a * reference to the array. This increases the refCount of the * instance, used to track when the array can be deleted. * * This method must be called while holding a reference to the instance. * * If adjust parameter is true (default), adjust the index into the * devices array so that it falls within the current devices array. * This is needed because the devices array can be changed at any * time, and the index may be from the old array. But in some * cases we prefer to know that the index is incorrect. * */ AwtWin32GraphicsDevice *Devices::GetDeviceReference(int index, BOOL adjust) { J2dTraceLn2(J2D_TRACE_INFO, "Devices::GetDeviceReference index=%d adjust?=%d", index, adjust); AwtWin32GraphicsDevice * ret = GetDevice(index, adjust); if (ret != NULL) { AddReference(); } return ret; }
/* * Class: sun_java2d_windows_GDIRenderer * Method: doDrawArc * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_windows_GDIRenderer_doDrawArc (JNIEnv *env, jobject wr, jobject sData, jobject clip, jobject comp, jint color, jint x, jint y, jint w, jint h, jint angleStart, jint angleExtent) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawArc"); J2dTraceLn5(J2D_TRACE_VERBOSE, " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", color, x, y, w, h); J2dTraceLn2(J2D_TRACE_VERBOSE, " angleStart=%-4d angleExtent=%-4d", angleStart, angleExtent); if (w < 0 || h < 0 || angleExtent == 0) { return; } GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData); if (wsdo == NULL) { return; } long sx, sy, ex, ey; if (angleExtent >= 360 || angleExtent <= -360) { sx = ex = x + w; sy = ey = y + h/2; } else { int angleEnd; if (angleExtent < 0) { angleEnd = angleStart; angleStart += angleExtent; } else { angleEnd = angleStart + angleExtent; } AngleToCoord(angleStart, w, h, &sx, &sy); sx += x + w/2; sy += y + h/2; AngleToCoord(angleEnd, w, h, &ex, &ey); ex += x + w/2; ey += y + h/2; } HDC hdc = wsdo->GetDC(env, wsdo, PEN, NULL, clip, comp, color); if (hdc == NULL) { return; } ::Arc(hdc, x, y, x+w+1, y+h+1, sx, sy, ex, ey); wsdo->ReleaseDC(env, wsdo, hdc); }
HRESULT D3DVertexCacher::EnsureCapacity(D3DPRIMITIVETYPE newPType, UINT vNum) { HRESULT res = D3D_OK; if (vNum > MAX_BATCH_SIZE) { // REMIND: need to define our own errors return D3DERR_NOTAVAILABLE; } if ((firstUnusedVertex + vNum) > MAX_BATCH_SIZE) { // if we can't fit new vertices in the vertex buffer, // render whatever we have in the buffer and start // from the beginning of the vertex buffer J2dTraceLn2(J2D_TRACE_VERBOSE, "D3DVC::EnsureCapacity exceeded capacity. "\ "current v: %d, requested vertices: %d\n", firstUnusedVertex, vNum); if (FAILED(res = Render(RESET_ACTION))) { return res; } } J2dTraceLn5(J2D_TRACE_VERBOSE, "D3DVC::EnsureCapacity current batch: %d "\ " batch.type=%d newType=%d vNum=%d firstUnusedV=%d", currentBatch, batches[currentBatch].pType, newPType, vNum, firstUnusedVertex); // there should not be multiple linestrips in a batch, // or they will be counted as a single line strip if (batches[currentBatch].pType != newPType || batches[currentBatch].pType == D3DPT_LINESTRIP) { // if this is a first unused batch, use it if (firstUnusedVertex == firstPendingVertex) { // record the first batch and vertex scheduled for rendering firstPendingBatch = currentBatch; firstPendingVertex = firstUnusedVertex; } else { // otherwise go to the next batch currentBatch++; } batches[currentBatch].pType = newPType; batches[currentBatch].pNum = 0; } // firstUnusedVertex is updated when new vertices are added // to the vertices array return res; }
/** * This function initializes a native window surface and caches the window * bounds in the given OGLSDOps. Returns JNI_TRUE if the operation was * successful; JNI_FALSE otherwise. */ jboolean OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo) { GLXSDOps *glxsdo; Window window; XWindowAttributes attr; J2dTraceLn(J2D_TRACE_INFO, "OGLSD_InitOGLWindow"); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: ops are null"); return JNI_FALSE; } glxsdo = (GLXSDOps *)oglsdo->privOps; if (glxsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: glx ops are null"); return JNI_FALSE; } window = glxsdo->window; if (window == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: window is invalid"); return JNI_FALSE; } XGetWindowAttributes(awt_display, window, &attr); oglsdo->width = attr.width; oglsdo->height = attr.height; oglsdo->drawableType = OGLSD_WINDOW; oglsdo->isOpaque = JNI_TRUE; oglsdo->xOffset = 0; oglsdo->yOffset = 0; glxsdo->drawable = window; glxsdo->xdrawable = window; J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", oglsdo->width, oglsdo->height); return JNI_TRUE; }
// REMIND: this method is currently unused; consider removing it later... HRESULT D3DResourceManager::CreateOSPSurface(UINT width, UINT height, D3DFORMAT fmt, D3DResource** ppSurfaceResource/*out*/) { HRESULT res; IDirect3DDevice9 *pd3dDevice; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::CreateOSPSurface"); J2dTraceLn2(J2D_TRACE_VERBOSE, " w=%d h=%d", width, height); if (pCtx == NULL || ppSurfaceResource == NULL || (pd3dDevice = pCtx->Get3DDevice()) == NULL) { return E_FAIL; } if (FAILED(res = pd3dDevice->TestCooperativeLevel())) { return res; } // since the off-screen plain surface is intended to be used with // the UpdateSurface() method, it is essential that it be created // in the same format as the destination and allocated in the // SYSTEMMEM pool (otherwise UpdateSurface() will fail) D3DFORMAT format; if (fmt == D3DFMT_UNKNOWN) { format = pCtx->GetPresentationParams()->BackBufferFormat; } else { format = fmt; } D3DPOOL pool = D3DPOOL_SYSTEMMEM; IDirect3DSurface9 *pSurface = NULL; res = pd3dDevice->CreateOffscreenPlainSurface(width, height, format, pool, &pSurface, NULL); if (SUCCEEDED(res)) { J2dTraceLn1(J2D_TRACE_VERBOSE, " created OSP Surface: 0x%x ",pSurface); *ppSurfaceResource = new D3DResource((IDirect3DResource9*)pSurface); res = AddResource(*ppSurfaceResource); } else { DebugPrintD3DError(res, "D3DRM::CreateOSPSurface failed"); ppSurfaceResource = NULL; } return res; }
/** * Returns a reference to a device with the passed index. * * This method does not increase the ref count of the Devices instance. * * This method must be called while holding a reference to the instance. */ AwtWin32GraphicsDevice *Devices::GetDevice(int index, BOOL adjust) { J2dTraceLn2(J2D_TRACE_INFO, "Devices::GetDevice index=%d adjust?=%d", index, adjust); if (index < 0 || index >= numDevices) { if (!adjust) { J2dTraceLn1(J2D_TRACE_WARNING, "Devices::GetDevice: "\ "incorrect index %d, returning NULL.", index); return NULL; } J2dTraceLn1(J2D_TRACE_WARNING, "Devices::GetDevice: "\ "adjusted index %d to 0.", index); index = 0; } return devices[index]; }
/** * Initializes an OpenGL texture, using the given width and height as * a guide. See OGLSD_InitTextureObject() for more information. */ JNIEXPORT jboolean JNICALL Java_sun_java2d_opengl_OGLSurfaceData_initTexture (JNIEnv *env, jobject oglsd, jlong pData, jboolean isOpaque, jboolean texNonPow2, jboolean texRect, jint width, jint height) { OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); J2dTraceLn2(J2D_TRACE_INFO, "OGLSurfaceData_initTexture: w=%d h=%d", width, height); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_initTexture: ops are null"); return JNI_FALSE; } /* * We only use the GL_ARB_texture_rectangle extension if it is available * and the requested bounds are not pow2 (it is probably faster to use * GL_TEXTURE_2D for pow2 textures, and besides, our TexturePaint * code relies on GL_REPEAT, which is not allowed for * GL_TEXTURE_RECTANGLE_ARB targets). */ texRect = texRect && !OGLSD_IsPowerOfTwo(width, height); if (!OGLSD_InitTextureObject(oglsdo, isOpaque, texNonPow2, texRect, width, height)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_initTexture: could not init texture object"); return JNI_FALSE; } OGLSD_SetNativeDimensions(env, oglsdo, oglsdo->textureWidth, oglsdo->textureHeight); oglsdo->drawableType = OGLSD_TEXTURE; // other fields (e.g. width, height) are set in OGLSD_InitTextureObject() return JNI_TRUE; }
/** * This implementation first copies the alpha tile into a texture and then * maps that texture to the destination surface. This approach appears to * offer the best performance despite being a two-step process. * * When the source paint is a Color, we can simply use the GL_MODULATE * function to multiply the current color (already premultiplied with the * extra alpha value from the AlphaComposite) with the alpha value from * the mask texture tile. In picture form, this process looks like: * * A R G B * primary color Pa Pr Pg Pb (modulated with...) * texture unit 0 Ca Ca Ca Ca * --------------------------------------- * resulting color Ra Rr Rg Rb * * where: * Px = current color (already premultiplied by extra alpha) * Cx = coverage value from mask tile * Rx = resulting color/alpha component * * When the source paint is not a Color, it means that we are rendering with * a complex paint (e.g. GradientPaint, TexturePaint). In this case, we * rely on the GL_ARB_multitexture extension to effectively multiply the * paint fragments (autogenerated on texture unit 1, see the * OGLPaints_Set{Gradient,Texture,etc}Paint() methods for more details) * with the coverage values from the mask texture tile (provided on texture * unit 0), all of which is multiplied with the current color value (which * contains the extra alpha value). In picture form: * * A R G B * primary color Ea Ea Ea Ea (modulated with...) * texture unit 0 Ca Ca Ca Ca (modulated with...) * texture unit 1 Pa Pr Pg Pb * --------------------------------------- * resulting color Ra Rr Rg Rb * * where: * Ea = extra alpha * Cx = coverage value from mask tile * Px = gradient/texture paint color (generated for each fragment) * Rx = resulting color/alpha component * * Here are some descriptions of the many variables used in this method: * x,y - upper left corner of the tile destination * w,h - width/height of the mask tile * x0 - placekeeper for the original destination x location * tw,th - width/height of the actual texture tile in pixels * sx1,sy1 - upper left corner of the mask tile source region * sx2,sy2 - lower left corner of the mask tile source region * sx,sy - "current" upper left corner of the mask tile region of interest */ void OGLMaskFill_MaskFill(OGLContext *oglc, jint x, jint y, jint w, jint h, jint maskoff, jint maskscan, jint masklen, unsigned char *pMask) { J2dTraceLn(J2D_TRACE_INFO, "OGLMaskFill_MaskFill"); RETURN_IF_NULL(oglc); CHECK_PREVIOUS_OP(OGL_STATE_MASK_OP); J2dTraceLn4(J2D_TRACE_VERBOSE, " x=%d y=%d w=%d h=%d", x, y, w, h); J2dTraceLn2(J2D_TRACE_VERBOSE, " maskoff=%d maskscan=%d", maskoff, maskscan); { jint tw, th, x0; jint sx1, sy1, sx2, sy2; jint sx, sy, sw, sh; x0 = x; tw = OGLVC_MASK_CACHE_TILE_WIDTH; th = OGLVC_MASK_CACHE_TILE_HEIGHT; sx1 = maskoff % maskscan; sy1 = maskoff / maskscan; sx2 = sx1 + w; sy2 = sy1 + h; for (sy = sy1; sy < sy2; sy += th, y += th) { x = x0; sh = ((sy + th) > sy2) ? (sy2 - sy) : th; for (sx = sx1; sx < sx2; sx += tw, x += tw) { sw = ((sx + tw) > sx2) ? (sx2 - sx) : tw; OGLVertexCache_AddMaskQuad(oglc, sx, sy, x, y, sw, sh, maskscan, pMask); } } } }
/** * Returns cell info associated with particular cache from the glyph's list of * cached cells. */ CacheCellInfo * AccelGlyphCache_GetCellInfoForCache(GlyphInfo *glyph, GlyphCacheInfo *cache) { // assert (glyph != NULL && cache != NULL) J2dTraceLn(J2D_TRACE_VERBOSE2, "AccelGlyphCache_GetCellInfoForCache"); if (glyph->cellInfo != NULL) { CacheCellInfo *cellInfo = glyph->cellInfo; do { if (cellInfo->cacheInfo == cache) { J2dTraceLn3(J2D_TRACE_VERBOSE2, " glyph 0x%x: found cell 0x%x for cache 0x%x", glyph, cellInfo, cache); return cellInfo; } cellInfo = cellInfo->nextGCI; } while (cellInfo != NULL); } J2dTraceLn2(J2D_TRACE_VERBOSE2, " glyph 0x%x: no cell for cache 0x%x", glyph, cache); return NULL; }
/** * Initializes the OpenGL blending state. XOR mode is disabled and the * appropriate blend functions are setup based on the AlphaComposite rule * constant. */ void OGLContext_SetAlphaComposite(OGLContext *oglc, jint rule, jfloat extraAlpha, jint flags) { J2dTraceLn1(J2D_TRACE_INFO, "OGLContext_SetAlphaComposite: flags=%d", flags); RETURN_IF_NULL(oglc); CHECK_PREVIOUS_OP(OGL_STATE_CHANGE); // disable XOR mode if (oglc->compState == sun_java2d_SunGraphics2D_COMP_XOR) { j2d_glDisable(GL_COLOR_LOGIC_OP); j2d_glDisable(GL_ALPHA_TEST); } // we can safely disable blending when: // - comp is SrcNoEa or SrcOverNoEa, and // - the source is opaque // (turning off blending can have a large positive impact on // performance) if ((rule == RULE_Src || rule == RULE_SrcOver) && (extraAlpha == 1.0f) && (flags & OGLC_SRC_IS_OPAQUE)) { J2dTraceLn1(J2D_TRACE_VERBOSE, " disabling alpha comp: rule=%d ea=1.0 src=opq", rule); j2d_glDisable(GL_BLEND); } else { J2dTraceLn2(J2D_TRACE_VERBOSE, " enabling alpha comp: rule=%d ea=%f", rule, extraAlpha); j2d_glEnable(GL_BLEND); j2d_glBlendFunc(StdBlendRules[rule].src, StdBlendRules[rule].dst); } // update state oglc->compState = sun_java2d_SunGraphics2D_COMP_ALPHA; oglc->extraAlpha = extraAlpha; }
/* * Class: sun_java2d_windows_GDIRenderer * Method: doDrawRoundRect * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_windows_GDIRenderer_doDrawRoundRect (JNIEnv *env, jobject wr, jobject sData, jobject clip, jobject comp, jint color, jint x, jint y, jint w, jint h, jint arcW, jint arcH) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawRoundRect"); J2dTraceLn5(J2D_TRACE_VERBOSE, " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", color, x, y, w, h); J2dTraceLn2(J2D_TRACE_VERBOSE, " arcW=%-4d arcH=%-4d", arcW, arcH); if (w < 2 || h < 2 || arcW <= 0 || arcH <= 0) { // Fix for 4524760 - drawRoundRect0 test case fails on Windows 98 // Thin round rects degenerate into regular rectangles // because there is no room for the arc sections. Also // if there is no arc dimension then the roundrect must // be a simple rectangle. Defer to the DrawRect function // which handles degenerate sizes better. Java_sun_java2d_windows_GDIRenderer_doDrawRect(env, wr, sData, clip, comp, color, x, y, w, h); return; } GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData); if (wsdo == NULL) { return; } HDC hdc = wsdo->GetDC(env, wsdo, PENONLY, NULL, clip, comp, color); if (hdc == NULL) { return; } ::RoundRect(hdc, x, y, x+w+1, y+h+1, arcW, arcH); wsdo->ReleaseDC(env, wsdo, hdc); }
/* * Class: sun_java2d_windows_GDIRenderer * Method: doFillRoundRect * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIIIII)V */ JNIEXPORT void JNICALL Java_sun_java2d_windows_GDIRenderer_doFillRoundRect (JNIEnv *env, jobject wr, jobject sData, jobject clip, jobject comp, jint color, jint x, jint y, jint w, jint h, jint arcW, jint arcH) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doFillRoundRect"); J2dTraceLn5(J2D_TRACE_VERBOSE, " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", color, x, y, w, h); J2dTraceLn2(J2D_TRACE_VERBOSE, " arcW=%-4d arcH=%-4d", arcW, arcH); if (w < 2 || h < 2 || arcW <= 0 || arcH <= 0) { // Fix related to 4524760 - drawRoundRect0 fails on Windows 98 // Thin round rects have no room for curvature. Also, if // the curvature is empty then the primitive has degenerated // into a simple rectangle. Defer to the FillRect method // which deals with degenerate sizes better. Java_sun_java2d_windows_GDIRenderer_doFillRect(env, wr, sData, clip, comp, color, x, y, w, h); return; } GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData); if (wsdo == NULL) { return; } HDC hdc = wsdo->GetDC(env, wsdo, BRUSHONLY, NULL, clip, comp, color); if (hdc == NULL) { return; } ::RoundRect(hdc, x, y, x+w+1, y+h+1, arcW, arcH); wsdo->ReleaseDC(env, wsdo, hdc); }
/** * This function initializes a native window surface and caches the window * bounds in the given OGLSDOps. Returns JNI_TRUE if the operation was * successful; JNI_FALSE otherwise. */ jboolean OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo) { GLXSDOps *glxsdo; Window window; #ifdef XAWT XWindowAttributes attr; #else Widget widget; #endif J2dTraceLn(J2D_TRACE_INFO, "OGLSD_InitOGLWindow"); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: ops are null"); return JNI_FALSE; } glxsdo = (GLXSDOps *)oglsdo->privOps; if (glxsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: glx ops are null"); return JNI_FALSE; } #ifdef XAWT window = glxsdo->window; if (window == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: window is invalid"); return JNI_FALSE; } XGetWindowAttributes(awt_display, window, &attr); oglsdo->width = attr.width; oglsdo->height = attr.height; #else widget = glxsdo->widget; if (widget == NULL) { J2dTraceLn(J2D_TRACE_WARNING, "OGLSD_InitOGLWindow: widget is null"); } if (!XtIsRealized(widget)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: widget is unrealized"); return JNI_FALSE; } window = XtWindow(widget); oglsdo->width = widget->core.width; oglsdo->height = widget->core.height; #endif oglsdo->drawableType = OGLSD_WINDOW; oglsdo->isOpaque = JNI_TRUE; oglsdo->xOffset = 0; oglsdo->yOffset = 0; glxsdo->drawable = window; glxsdo->xdrawable = window; J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", oglsdo->width, oglsdo->height); return JNI_TRUE; }
// static BOOL Devices::UpdateInstance(JNIEnv *env) { J2dTraceLn(J2D_TRACE_INFO, "Devices::UpdateInstance"); int numScreens = ::CountMonitors(); MHND *monHds = (MHND *)safe_Malloc(numScreens * sizeof(MHND)); if (numScreens != ::CollectMonitors(monHds, numScreens)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "Devices::UpdateInstance: Failed to get all "\ "monitor handles."); free(monHds); return FALSE; } Devices *newDevices = new Devices(numScreens); // This way we know that the array will not be disposed of // at least until we replaced it with a new one. newDevices->AddReference(); // Create all devices first, then initialize them. This allows // correct configuration of devices after contruction of the // primary device (which may not be device 0). AwtWin32GraphicsDevice** rawDevices = newDevices->GetRawArray(); int i; for (i = 0; i < numScreens; ++i) { J2dTraceLn2(J2D_TRACE_VERBOSE, " hmon[%d]=0x%x", i, monHds[i]); rawDevices[i] = new AwtWin32GraphicsDevice(i, monHds[i], newDevices); } for (i = 0; i < numScreens; ++i) { rawDevices[i]->Initialize(); } { CriticalSection::Lock l(arrayLock); // install the new devices array Devices *oldDevices = theInstance; theInstance = newDevices; if (oldDevices) { // Invalidate the devices with indexes out of the new set of // devices. This doesn't cover all cases when the device // might should be invalidated (like if it's not the last device // that was removed), but it will have to do for now. int oldNumScreens = oldDevices->GetNumDevices(); int newNumScreens = theInstance->GetNumDevices(); J2dTraceLn(J2D_TRACE_VERBOSE, " Invalidating removed devices"); for (int i = newNumScreens; i < oldNumScreens; i++) { // removed device, needs to be invalidated J2dTraceLn1(J2D_TRACE_WARNING, "Devices::UpdateInstance: device removed: %d", i); oldDevices->GetDevice(i)->Invalidate(env); } // Now that we have a new array in place, remove this (possibly the // last) reference to the old instance. oldDevices->Release(); } D3DPipelineManager::HandleAdaptersChange((HMONITOR*)monHds, theInstance->GetNumDevices()); } free(monHds); return TRUE; }
/** * This implementation of MaskBlit first combines the source system memory * tile with the corresponding alpha mask and stores the resulting * IntArgbPre pixels directly into the RenderBuffer. Those pixels are * then eventually pulled off the RenderBuffer and copied to the destination * surface in OGL/D3DMaskBlit. * * Note that currently there are only inner loops defined for IntArgb, * IntArgbPre, IntRgb, and IntBgr, as those are the most commonly used * formats for this operation. */ JNIEXPORT jint JNICALL Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile (JNIEnv *env, jobject mb, jlong buf, jint bpos, jobject srcData, jlong pSrcOps, jint srcType, jbyteArray maskArray, jint masklen, jint maskoff, jint maskscan, jint srcx, jint srcy, jint dstx, jint dsty, jint width, jint height) { SurfaceDataOps *srcOps = (SurfaceDataOps *)jlong_to_ptr(pSrcOps); SurfaceDataRasInfo srcInfo; unsigned char *pMask; unsigned char *bbuf; jint *pBuf; J2dTraceLn1(J2D_TRACE_INFO, "BufferedMaskBlit_enqueueTile: bpos=%d", bpos); if (srcOps == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "BufferedMaskBlit_enqueueTile: srcOps is null"); return bpos; } bbuf = (unsigned char *)jlong_to_ptr(buf); if (bbuf == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "BufferedMaskBlit_enqueueTile: cannot get direct buffer address"); return bpos; } pBuf = (jint *)(bbuf + bpos); if (JNU_IsNull(env, maskArray)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "BufferedMaskBlit_enqueueTile: mask array is null"); return bpos; } if (masklen > MAX_MASK_LENGTH) { // REMIND: this approach is seriously flawed if the mask // length is ever greater than MAX_MASK_LENGTH (won't fit // into the cached mask tile); so far this hasn't // been a problem though... J2dRlsTraceLn(J2D_TRACE_ERROR, "BufferedMaskBlit_enqueueTile: mask array too large"); return bpos; } pMask = (*env)->GetPrimitiveArrayCritical(env, maskArray, 0); if (pMask == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "BufferedMaskBlit_enqueueTile: cannot lock mask array"); return bpos; } srcInfo.bounds.x1 = srcx; srcInfo.bounds.y1 = srcy; srcInfo.bounds.x2 = srcx + width; srcInfo.bounds.y2 = srcy + height; if (srcOps->Lock(env, srcOps, &srcInfo, SD_LOCK_READ) != SD_SUCCESS) { J2dRlsTraceLn(J2D_TRACE_WARNING, "BufferedMaskBlit_enqueueTile: could not acquire lock"); (*env)->ReleasePrimitiveArrayCritical(env, maskArray, pMask, JNI_ABORT); return bpos; } if (srcInfo.bounds.x2 > srcInfo.bounds.x1 && srcInfo.bounds.y2 > srcInfo.bounds.y1) { srcOps->GetRasInfo(env, srcOps, &srcInfo); if (srcInfo.rasBase) { jint h; jint srcScanStride = srcInfo.scanStride; jint srcPixelStride = srcInfo.pixelStride; jint *pSrc = (jint *) PtrCoord(srcInfo.rasBase, srcInfo.bounds.x1, srcInfo.pixelStride, srcInfo.bounds.y1, srcInfo.scanStride); width = srcInfo.bounds.x2 - srcInfo.bounds.x1; height = srcInfo.bounds.y2 - srcInfo.bounds.y1; maskoff += ((srcInfo.bounds.y1 - srcy) * maskscan + (srcInfo.bounds.x1 - srcx)); maskscan -= width; pMask += maskoff; srcScanStride -= width * srcPixelStride; h = height; J2dTraceLn4(J2D_TRACE_VERBOSE, " sx=%d sy=%d w=%d h=%d", srcInfo.bounds.x1, srcInfo.bounds.y1, width, height); J2dTraceLn2(J2D_TRACE_VERBOSE, " maskoff=%d maskscan=%d", maskoff, maskscan); J2dTraceLn2(J2D_TRACE_VERBOSE, " pixstride=%d scanstride=%d", srcPixelStride, srcScanStride); // enqueue parameters pBuf[0] = sun_java2d_pipe_BufferedOpCodes_MASK_BLIT; pBuf[1] = dstx; pBuf[2] = dsty; pBuf[3] = width; pBuf[4] = height; pBuf += 5; bpos += 5 * sizeof(jint); // apply alpha values from mask to the source tile, and store // resulting IntArgbPre pixels into RenderBuffer (there are // separate inner loops for the most common source formats) switch (srcType) { case sun_java2d_pipe_BufferedMaskBlit_ST_INT_ARGB: do { jint w = width; do { jubyte pathA = *pMask++; if (!pathA) { pBuf[0] = 0; } else { jint cr, cg, cb, ca; jubyte r, g, b, a; LoadIntArgbTo4ByteArgb(pSrc, c, 0, ca, cr, cg, cb); a = MUL8(ca, pathA); r = MUL8(cr, a); g = MUL8(cg, a); b = MUL8(cb, a); pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b; } pSrc = PtrAddBytes(pSrc, srcPixelStride); pBuf++; } while (--w > 0); pSrc = PtrAddBytes(pSrc, srcScanStride); pMask = PtrAddBytes(pMask, maskscan); } while (--h > 0); break; case sun_java2d_pipe_BufferedMaskBlit_ST_INT_ARGB_PRE: do { jint w = width; do { jubyte pathA = *pMask++; if (!pathA) { pBuf[0] = 0; } else if (pathA == 0xff) { pBuf[0] = pSrc[0]; } else { jubyte r, g, b, a; a = MUL8((pSrc[0] >> 24) & 0xff, pathA); r = MUL8((pSrc[0] >> 16) & 0xff, pathA); g = MUL8((pSrc[0] >> 8) & 0xff, pathA); b = MUL8((pSrc[0] >> 0) & 0xff, pathA); pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b; } pSrc = PtrAddBytes(pSrc, srcPixelStride); pBuf++; } while (--w > 0); pSrc = PtrAddBytes(pSrc, srcScanStride); pMask = PtrAddBytes(pMask, maskscan); } while (--h > 0); break; case sun_java2d_pipe_BufferedMaskBlit_ST_INT_RGB: do { jint w = width; do { jubyte pathA = *pMask++; if (!pathA) { pBuf[0] = 0; } else { jint cr, cg, cb; jubyte r, g, b, a; LoadIntRgbTo3ByteRgb(pSrc, c, 0, cr, cg, cb); a = pathA; r = MUL8(cr, a); g = MUL8(cg, a); b = MUL8(cb, a); pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b; } pSrc = PtrAddBytes(pSrc, srcPixelStride); pBuf++; } while (--w > 0); pSrc = PtrAddBytes(pSrc, srcScanStride); pMask = PtrAddBytes(pMask, maskscan); } while (--h > 0); break; case sun_java2d_pipe_BufferedMaskBlit_ST_INT_BGR: do { jint w = width; do { jubyte pathA = *pMask++; if (!pathA) { pBuf[0] = 0; } else { jint cr, cg, cb; jubyte r, g, b, a; LoadIntBgrTo3ByteRgb(pSrc, c, 0, cr, cg, cb); a = pathA; r = MUL8(cr, a); g = MUL8(cg, a); b = MUL8(cb, a); pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b; } pSrc = PtrAddBytes(pSrc, srcPixelStride); pBuf++; } while (--w > 0); pSrc = PtrAddBytes(pSrc, srcScanStride); pMask = PtrAddBytes(pMask, maskscan); } while (--h > 0); break; default: // should not get here, just no-op... break; } // increment current byte position bpos += width * height * sizeof(jint); }
/* * Class: sun_java2d_d3d_D3DSurfaceData * Method: initOffScreenSurface * Signature: (JJJIIII)I */ JNIEXPORT jint JNICALL Java_sun_java2d_d3d_D3DSurfaceData_initOffScreenSurface (JNIEnv *env, jobject sData, jlong pCtx, jlong pData, jlong parentPdata, jint width, jint height, jint d3dSurfaceType, jint screen) { Win32SDOps *wsdo = (Win32SDOps *)jlong_to_ptr(pData); D3DContext *pd3dc = (D3DContext *)jlong_to_ptr(pCtx); J2dTraceLn(J2D_TRACE_INFO, "D3DSurfaceData_initOffScreenSurface"); J2dTraceLn4(J2D_TRACE_VERBOSE, " width=%-4d height=%-4d type=%-3d scr=%-3d", width, height, d3dSurfaceType, screen); // REMIND: ideally this should be done in initOps if (d3dSurfaceType == D3D_ATTACHED_SURFACE) { wsdo->sdOps.Dispose = Win32BBSD_Dispose; } if (init_D3DSDO(env, wsdo, width, height, d3dSurfaceType, screen) == JNI_FALSE) { SurfaceData_ThrowInvalidPipeException(env, "Can't create offscreen surface"); return PF_INVALID; } HMONITOR hMon = (HMONITOR)wsdo->device->GetMonitor(); DDrawObjectStruct *ddInstance = GetDDInstanceForDevice(hMon); if (!ddInstance || !ddInstance->valid || !pd3dc) { return PF_INVALID; } if (d3dSurfaceType == D3D_ATTACHED_SURFACE) { // REMIND: still using the old path. ideally the creation of attached // surface shoudld be done in the same way as other types of surfaces, // that is, in D3DContext::CreateSurface, but we really don't use // anything from D3DContext to get an attached surface, so this // was left here. Win32SDOps *wsdo_parent = (Win32SDOps *)jlong_to_ptr(parentPdata); // we're being explicit here: requesting backbuffer, and render target DDrawSurface* pNew = wsdo_parent->lpSurface == NULL ? NULL : wsdo_parent->lpSurface-> GetDDAttachedSurface(DDSCAPS_BACKBUFFER|DDSCAPS_3DDEVICE); if (pNew == NULL || FAILED(pd3dc->AttachDepthBuffer(pNew->GetDXSurface()))) { J2dRlsTraceLn1(J2D_TRACE_ERROR, "D3DSD_initSurface: GetAttachedSurface for parent"\ " wsdo_parent->lpSurface=0x%x failed", wsdo_parent->lpSurface); if (pNew != NULL) { delete pNew; } SurfaceData_ThrowInvalidPipeException(env, "Can't create attached offscreen surface"); return PF_INVALID; } wsdo->lpSurface = pNew; wsdo->ddInstance = ddInstance; J2dTraceLn2(J2D_TRACE_VERBOSE, "D3DSD_initSurface: created attached surface: "\ "wsdo->lpSurface=0x%x for parent "\ "wsdo_parent->lpSurface=0x%x", wsdo->lpSurface, wsdo_parent->lpSurface); // we don't care about pixel format for non-texture surfaces return PF_INVALID; } DXSurface *dxSurface = NULL; jint pf = PF_INVALID; HRESULT res; if (SUCCEEDED(res = pd3dc->CreateSurface(env, wsdo->w, wsdo->h, wsdo->depth, wsdo->transparency, d3dSurfaceType, &dxSurface, &pf))) { // REMIND: put all the error-handling stuff here from // DDCreateOffScreenSurface wsdo->lpSurface = new DDrawSurface(ddInstance->ddObject, dxSurface); wsdo->surfacePuntData.lpSurfaceVram = wsdo->lpSurface; wsdo->ddInstance = ddInstance; // the dimensions of the surface may be adjusted in case of // textures wsdo->w = dxSurface->GetWidth(); wsdo->h = dxSurface->GetHeight(); J2dTraceLn1(J2D_TRACE_VERBOSE, "D3DSurfaceData_initSurface: created surface: "\ "wsdo->lpSurface=0x%x", wsdo->lpSurface); } else { DebugPrintDirectDrawError(res, "D3DSurfaceData_initSurface: "\ "CreateSurface failed"); // REMIND: should use some other way to signal that // surface creation was unsuccessful SurfaceData_ThrowInvalidPipeException(env, "Can't create offscreen surf"); } return pf; }
JNIEXPORT jint JNICALL Java_sun_java2d_pipe_BufferedRenderPipe_fillSpans (JNIEnv *env, jobject pipe, jobject rq, jlong buf, jint bpos, jint limit, jobject si, jlong pIterator, jint transx, jint transy) { SpanIteratorFuncs *pFuncs = (SpanIteratorFuncs *)jlong_to_ptr(pIterator); void *srData; jint spanbox[4]; jint spanCount = 0; jint remainingBytes, remainingSpans; unsigned char *bbuf; jint *ibuf; jint ipos; J2dTraceLn2(J2D_TRACE_INFO, "BufferedRenderPipe_fillSpans: bpos=%d limit=%d", bpos, limit); if (JNU_IsNull(env, rq)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "BufferedRenderPipe_fillSpans: rq is null"); return bpos; } if (JNU_IsNull(env, si)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "BufferedRenderPipe_fillSpans: span iterator is null"); return bpos; } if (pFuncs == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "BufferedRenderPipe_fillSpans: native iterator not supplied"); return bpos; } bbuf = (unsigned char *)jlong_to_ptr(buf); if (bbuf == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "BufferedRenderPipe_fillSpans: cannot get direct buffer address"); return bpos; } // adjust the int pointer to the current buffer position ibuf = (jint *)(bbuf + bpos); // start new operation ibuf[0] = sun_java2d_pipe_BufferedOpCodes_FILL_SPANS; ibuf[1] = 0; // placeholder for the span count // skip the opcode and span count ipos = INTS_PER_HEADER; bpos += BYTES_PER_HEADER; // skip the opcode and span count remainingBytes = limit - bpos; remainingSpans = remainingBytes / BYTES_PER_SPAN; srData = (*pFuncs->open)(env, si); while ((*pFuncs->nextSpan)(srData, spanbox)) { if (remainingSpans == 0) { // fill in span count ibuf[1] = spanCount; // flush the queue JNU_CallMethodByName(env, NULL, rq, "flushNow", "(I)V", bpos); // now start a new operation ibuf = (jint *)bbuf; ibuf[0] = sun_java2d_pipe_BufferedOpCodes_FILL_SPANS; ibuf[1] = 0; // placeholder for the span count // skip the opcode and span count ipos = INTS_PER_HEADER; bpos = BYTES_PER_HEADER; // calculate new limits remainingBytes = limit - bpos; remainingSpans = remainingBytes / BYTES_PER_SPAN; spanCount = 0; } // enqueue span ibuf[ipos++] = spanbox[0] + transx; // x1 ibuf[ipos++] = spanbox[1] + transy; // y1 ibuf[ipos++] = spanbox[2] + transx; // x2 ibuf[ipos++] = spanbox[3] + transy; // y2 // update positions bpos += BYTES_PER_SPAN; spanCount++; remainingSpans--; } (*pFuncs->close)(env, srData); // fill in span count ibuf[1] = spanCount; // return the current byte position return bpos; }
HRESULT D3DVertexCacher::Render(int actionType) { J2DLVERTEX *lpVert; HRESULT res; DWORD dwLockFlags; UINT pendingVertices = firstUnusedVertex - firstPendingVertex; // nothing to render if (pendingVertices == 0) { if (actionType == RESET_ACTION) { firstPendingBatch = 0; firstPendingVertex = 0; firstUnusedVertex = 0; currentBatch = 0; } return D3D_OK; } if (firstPendingVertex == 0) { // no data in the buffer yet, we don't care about // vertex buffer's contents dwLockFlags = D3DLOCK_DISCARD; } else { // append to the existing data in the vertex buffer dwLockFlags = D3DLOCK_NOOVERWRITE; } if (SUCCEEDED(res = lpD3DVertexBuffer->Lock((UINT)firstPendingVertex*sizeof(J2DLVERTEX), (UINT)pendingVertices*sizeof(J2DLVERTEX), (void**)&lpVert, dwLockFlags))) { // copy only new vertices memcpy((void *)lpVert, (void *)(vertices + firstPendingVertex), pendingVertices * sizeof(J2DLVERTEX)); res = lpD3DVertexBuffer->Unlock(); UINT currentVertex = firstPendingVertex; UINT batchSize; J2dTraceLn2(J2D_TRACE_VERBOSE, "D3DVC::Render Starting flushing of %d vertices "\ "in %d batches", pendingVertices, (currentBatch - firstPendingBatch + 1)); for (UINT b = firstPendingBatch; b <= currentBatch; b++) { D3DPRIMITIVETYPE pType = batches[b].pType; UINT primCount = batches[b].pNum; switch (pType) { // the macro for adding a line segment adds one too many prims case D3DPT_LINESTRIP: batchSize = primCount; primCount--; break; case D3DPT_LINELIST: batchSize = primCount*2; break; default: batchSize = primCount*3; break; } res = lpD3DDevice->DrawPrimitive(pType, currentVertex, primCount); currentVertex += batchSize; // init to something it can never be batches[b].pType = (D3DPRIMITIVETYPE)0; batches[b].pNum = 0; } } else { DebugPrintD3DError(res, "Can't lock vertex buffer"); } // REMIND: may need to rethink what to do in case of an error, // should we try to render them later? if (actionType == RESET_ACTION) { firstPendingBatch = 0; firstPendingVertex = 0; firstUnusedVertex = 0; currentBatch = 0; } else { firstPendingBatch = currentBatch; firstPendingVertex = firstUnusedVertex; } return res; }
static void Win32OSSD_LockByDD(JNIEnv *env, Win32SDOps *wsdo, jint lockflags, SurfaceDataRasInfo *pRasInfo) { DTRACE_PRINTLN("Win32OSSD_LockByDD"); if ((lockflags & SD_LOCK_READ) && !wsdo->surfacePuntData.disablePunts) { wsdo->surfacePuntData.numBltsSinceRead = 0; if (!wsdo->surfacePuntData.usingDDSystem) { int w = pRasInfo->bounds.x2 - pRasInfo->bounds.x1; int h = pRasInfo->bounds.y2 - pRasInfo->bounds.y1; wsdo->surfacePuntData.pixelsReadSinceBlt += w * h; // Note that basing this decision on the bounds is somewhat // incorrect because locks of type FASTEST will simply send // in bounds that equal the area of the entire surface. // To do this correctly, we would need to return // SLOWLOCK and recalculate the punt data in GetRasInfo() if (wsdo->surfacePuntData.pixelsReadSinceBlt > wsdo->surfacePuntData.pixelsReadThreshold) { // Create the system surface if it doesn't exist if (!wsdo->surfacePuntData.lpSurfaceSystem) { wsdo->surfacePuntData.lpSurfaceSystem = wsdo->ddInstance->ddObject->CreateDDOffScreenSurface( wsdo->w, wsdo->h, wsdo->depth, FALSE /* don't need caps d3d for surfaces in system memory */, wsdo->transparency, DDSCAPS_SYSTEMMEMORY); if (wsdo->surfacePuntData.lpSurfaceSystem) { // 4941350: Double-check that the surface we created // matches the depth expected. int sysmemDepth = wsdo->surfacePuntData.lpSurfaceSystem->GetSurfaceDepth(); if (!DDSurfaceDepthsCompatible(wsdo->depth, sysmemDepth)) { // There is clearly a problem here; release // the punting surface J2dTraceLn2(J2D_TRACE_WARNING, "Punting error: Java/sys depths %d/%d", wsdo->depth, sysmemDepth); DDReleaseSurfaceMemory(wsdo->surfacePuntData. lpSurfaceSystem); wsdo->surfacePuntData.lpSurfaceSystem = NULL; } else { DDCOLORKEY ddck; HRESULT ddResult = wsdo->surfacePuntData.lpSurfaceVram->GetColorKey( DDCKEY_SRCBLT, &ddck); if (ddResult == DD_OK) { // Vram surface has colorkey - use same colorkey on sys ddResult = wsdo->surfacePuntData.lpSurfaceSystem->SetColorKey( DDCKEY_SRCBLT, &ddck); } } } } // Assuming no errors in system creation, copy contents if (wsdo->surfacePuntData.lpSurfaceSystem) { if (wsdo->surfacePuntData.lpSurfaceSystem->Blt(NULL, wsdo->surfacePuntData.lpSurfaceVram, NULL, DDBLT_WAIT, NULL) == DD_OK) { J2dTraceLn2(J2D_TRACE_INFO, "Win32OSSD: punting VRAM to sys: 0x%x -> 0x%x\n", wsdo->surfacePuntData.lpSurfaceSystem, wsdo->surfacePuntData.lpSurfaceVram); wsdo->lpSurface = wsdo->surfacePuntData.lpSurfaceSystem; wsdo->surfacePuntData.usingDDSystem = TRUE; // Notify the Java level that this surface has // been punted to avoid performance penalties from // copying from VRAM cached versions of other images // when we should use system memory versions instead. jobject sdObject = env->NewLocalRef(wsdo->sdOps.sdObject); if (sdObject) { // Only bother with this optimization if the // reference is still valid env->SetBooleanField(sdObject, ddSurfacePuntedID, JNI_TRUE); env->DeleteLocalRef(sdObject); } } } } } } if (!DDLock(env, wsdo, NULL, pRasInfo)) return; wsdo->lockType = WIN32SD_LOCK_BY_DDRAW; }