HRESULT D3DResourceManager::GetLockableRTSurface(UINT width, UINT height, D3DFORMAT format, D3DResource **ppSurfaceResource) { HRESULT res = S_OK; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetLockableRTSurface"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppSurfaceResource, E_FAIL); if (pLockableRTSurface != NULL) { D3DSURFACE_DESC *pDesc = pLockableRTSurface->GetDesc(); if (width <= pDesc->Width && height <= pDesc->Height && format == pDesc->Format) { *ppSurfaceResource = pLockableRTSurface; return res; } // current surface doesn't fit, release and allocate a new one ReleaseResource(pLockableRTSurface); pLockableRTSurface = NULL; } if (width < D3DC_BLIT_TILE_SIZE) width = D3DC_BLIT_TILE_SIZE; if (height < D3DC_BLIT_TILE_SIZE) height = D3DC_BLIT_TILE_SIZE; res = CreateRTSurface(width,height, (format != D3DFMT_A8R8G8B8), TRUE /*lockable*/, &format, &pLockableRTSurface); *ppSurfaceResource = pLockableRTSurface; return res; }
/* * Class: sun_java2d_d3d_D3DGraphicsDevice * Method: getAvailableAcceleratedMemoryNative * Signature: (I)J */ JNIEXPORT jlong JNICALL Java_sun_java2d_d3d_D3DGraphicsDevice_getAvailableAcceleratedMemoryNative (JNIEnv *env, jclass gdc, jint gdiScreen) { // REMIND: looks like Direct3D provides information about texture memory // only via IDirect3DDevice9::GetAvailableTextureMem, however, it // seems to report the same amount as direct draw used to. HRESULT res; D3DPipelineManager *pMgr; D3DContext *pCtx; IDirect3DDevice9 *pd3dDevice; UINT adapter; J2dTraceLn(J2D_TRACE_INFO, "D3DGD_getAvailableAcceleratedMemoryNative"); RETURN_STATUS_IF_NULL(pMgr = D3DPipelineManager::GetInstance(), 0L); adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen); if (FAILED(res = pMgr->GetD3DContext(adapter, &pCtx))) { D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination()); return 0L; } RETURN_STATUS_IF_NULL(pd3dDevice = pCtx->Get3DDevice(), 0L); UINT mem = pd3dDevice->GetAvailableTextureMem(); J2dTraceLn1(J2D_TRACE_VERBOSE, " available memory=%d", mem); return mem; }
/* * Class: sun_java2d_d3d_D3DGraphicsDevice * Method: getCurrentDisplayModeNative * Signature: (I)Ljava/awt/DisplayMode; */ JNIEXPORT jobject JNICALL Java_sun_java2d_d3d_D3DGraphicsDevice_getCurrentDisplayModeNative (JNIEnv *env, jclass gdc, jint gdiScreen) { D3DPipelineManager *pMgr; IDirect3D9 *pd3d9; jobject ret = NULL; D3DDISPLAYMODE mode; UINT adapter; J2dTraceLn(J2D_TRACE_INFO, "D3DGD_getCurrentDisplayModeNative"); RETURN_STATUS_IF_NULL(pMgr = D3DPipelineManager::GetInstance(), NULL); RETURN_STATUS_IF_NULL(pd3d9 = pMgr->GetD3DObject(), NULL); adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen); if (SUCCEEDED(pd3d9->GetAdapterDisplayMode(adapter, &mode))) { int bitDepth = -1; // these are the only three valid screen formats switch (mode.Format) { case D3DFMT_X8R8G8B8: bitDepth = 32; break; case D3DFMT_R5G6B5: case D3DFMT_X1R5G5B5: bitDepth = 16; break; } J2dTraceLn4(J2D_TRACE_VERBOSE, " current dm: %dx%dx%d@%d", mode.Width, mode.Height, bitDepth, mode.RefreshRate); ret = CreateDisplayMode(env, mode.Width, mode.Height, bitDepth, mode.RefreshRate); } return ret; }
HRESULT D3DResourceManager::GetCachedDestTexture(D3DFORMAT format, D3DResource **ppTextureResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetCachedDestTexture"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppTextureResource, E_FAIL); HRESULT res = GetStockTextureResource(D3DTR_CACHED_DEST_WIDTH, D3DTR_CACHED_DEST_HEIGHT, TRUE/*isRTT*/, FALSE/*isOpaque*/, &format, 0, &pCachedDestTexture); if (SUCCEEDED(res)) { D3DSURFACE_DESC *pDesc = pCachedDestTexture->GetDesc(); D3DCAPS9 *pDevCaps = pCtx->GetDeviceCaps(); if ((format == pDesc->Format || SUCCEEDED(pCtx->Get3DObject()->CheckDeviceFormatConversion( pDevCaps->AdapterOrdinal, pDevCaps->DeviceType, format, pDesc->Format)))) { *ppTextureResource = pCachedDestTexture; return res; } // current texture doesn't fit, release and allocate a new one ReleaseResource(pCachedDestTexture); pCachedDestTexture = NULL; } res = CreateTexture(D3DTR_CACHED_DEST_WIDTH, D3DTR_CACHED_DEST_HEIGHT, TRUE, FALSE, &format, 0, &pCachedDestTexture); *ppTextureResource = pCachedDestTexture; return res; }
HRESULT D3DResourceManager::GetBlitOSPSurface(UINT width, UINT height, D3DFORMAT fmt, D3DResource **ppSurfaceResource) { HRESULT res = S_OK; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetBlitOSPSurface"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppSurfaceResource, E_FAIL); if (pBlitOSPSurface != NULL) { D3DSURFACE_DESC *pDesc = pBlitOSPSurface->GetDesc(); if (width == pDesc->Width && height == pDesc->Height && (fmt == pDesc->Format || fmt == D3DFMT_UNKNOWN)) { *ppSurfaceResource = pBlitOSPSurface; return res; } // current surface doesn't fit, release and allocate a new one ReleaseResource(pBlitOSPSurface); pBlitOSPSurface = NULL; } res = CreateOSPSurface(width, height, fmt, &pBlitOSPSurface); *ppSurfaceResource = pBlitOSPSurface; return res; }
// 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; }
/* * Class: sun_java2d_d3d_D3DSurfaceData * Method: dbGetPixelNative * Signature: (JII)I */ JNIEXPORT jint JNICALL Java_sun_java2d_d3d_D3DSurfaceData_dbGetPixelNative (JNIEnv *env, jclass clazz, jlong pData, jint x, jint y) { HRESULT res; D3DSDOps *d3dsdo; D3DContext *pCtx; D3DPipelineManager *pMgr; D3DResource *pLockableRes; jint pixel = 0; J2dTraceLn(J2D_TRACE_INFO, "D3DSurfaceData_dbGetPixelNative"); RETURN_STATUS_IF_NULL(d3dsdo = (D3DSDOps *)jlong_to_ptr(pData), pixel); RETURN_STATUS_IF_NULL(d3dsdo->pResource, pixel); RETURN_STATUS_IF_NULL(pMgr = D3DPipelineManager::GetInstance(), pixel); if (FAILED(res = pMgr->GetD3DContext(d3dsdo->adapter, &pCtx))) { D3DRQ_MarkLostIfNeeded(res, d3dsdo); return pixel; } RETURN_STATUS_IF_NULL(pCtx->GetResourceManager(), 0); IDirect3DDevice9 *pd3dDevice = pCtx->Get3DDevice(); IDirect3DSurface9 *pSrc = d3dsdo->pResource->GetSurface(); D3DFORMAT srcFmt = d3dsdo->pResource->GetDesc()->Format; pCtx->UpdateState(STATE_OTHEROP); res = pCtx->GetResourceManager()-> GetLockableRTSurface(1, 1, srcFmt, &pLockableRes); if (SUCCEEDED(res)) { IDirect3DSurface9 *pTmpSurface; RECT srcRect = { x, y, x+1, y+1}; RECT dstRect = { 0l, 0l, 1, 1 }; pTmpSurface = pLockableRes->GetSurface(); res = pd3dDevice->StretchRect(pSrc, &srcRect, pTmpSurface, &dstRect, D3DTEXF_NONE); if (SUCCEEDED(res)) { D3DLOCKED_RECT lRect; res = pTmpSurface->LockRect(&lRect, &dstRect, D3DLOCK_NOSYSLOCK); if (SUCCEEDED(res)) { if (srcFmt == D3DFMT_X8R8G8B8) { pixel = *(jint*)lRect.pBits; } else { pixel = *(unsigned short*)lRect.pBits; } pTmpSurface->UnlockRect(); } } } D3DRQ_MarkLostIfNeeded(res, d3dsdo); return pixel; }
HRESULT D3DResourceManager::GetMultiGradientTexture(D3DResource **ppTextureResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetMultiGradientTexture"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppTextureResource, E_FAIL); HRESULT res = GetStockTextureResource(MAX_MULTI_GRADIENT_COLORS, 1, FALSE/*isRTT*/, FALSE/*isOpaque*/, NULL, 0, &pMultiGradientTexture); *ppTextureResource = pMultiGradientTexture; return res; }
HRESULT D3DResourceManager::GetMaskTexture(D3DResource **ppTextureResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetMaskTexture"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppTextureResource, E_FAIL); D3DFORMAT format = pCtx->IsTextureFormatSupported(D3DFMT_A8) ? D3DFMT_A8 : D3DFMT_A8R8G8B8; jboolean needsInit = (pMaskTexture == NULL); HRESULT res; if (FAILED(res = GetStockTextureResource(D3D_MASK_CACHE_WIDTH_IN_TEXELS, D3D_MASK_CACHE_HEIGHT_IN_TEXELS, FALSE/*isRTT*/, FALSE/*isOpaque*/, &format, 0, &pMaskTexture))) { return res; } if (needsInit) { // init special fully opaque tile in the upper-right corner of // the mask cache texture jubyte allOnes[D3D_MASK_CACHE_TILE_SIZE]; memset(allOnes, 0xff, D3D_MASK_CACHE_TILE_SIZE); if (FAILED(res = pCtx->UploadTileToTexture( pMaskTexture, allOnes, D3D_MASK_CACHE_SPECIAL_TILE_X, D3D_MASK_CACHE_SPECIAL_TILE_Y, 0, 0, D3D_MASK_CACHE_TILE_WIDTH, D3D_MASK_CACHE_TILE_HEIGHT, D3D_MASK_CACHE_TILE_WIDTH, TILEFMT_1BYTE_ALPHA))) { return res; } } *ppTextureResource = pMaskTexture; return res; }
HRESULT D3DResourceManager::GetLookupOpLutTexture(D3DResource **ppTextureResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetLookupOpTexture"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppTextureResource, E_FAIL); D3DFORMAT format = D3DFMT_L16; HRESULT res = GetStockTextureResource(256, 4, FALSE/*isRTT*/, FALSE/*isOpaque*/, &format, 0, &pLookupOpLutTexture); *ppTextureResource = pLookupOpLutTexture; return res; }
/* * Class: sun_java2d_d3d_D3DSurfaceData * Method: initTexture * Signature: (JZZ)Z */ JNIEXPORT jboolean JNICALL Java_sun_java2d_d3d_D3DSurfaceData_initTexture (JNIEnv *env, jobject d3dsd, jlong pData, jboolean isRTT, jboolean isOpaque) { HRESULT res; D3DSDOps *d3dsdo; D3DContext *pCtx; D3DPipelineManager *pMgr; D3DFORMAT format; J2dTraceLn(J2D_TRACE_INFO, "D3DSurfaceData_initTexture"); RETURN_STATUS_IF_NULL(d3dsdo = (D3DSDOps *)jlong_to_ptr(pData), JNI_FALSE); RETURN_STATUS_IF_NULL(pMgr = D3DPipelineManager::GetInstance(), JNI_FALSE); if (FAILED(res = pMgr->GetD3DContext(d3dsdo->adapter, &pCtx))) { D3DRQ_MarkLostIfNeeded(res, d3dsdo); return JNI_FALSE; } RETURN_STATUS_IF_NULL(pCtx->GetResourceManager(), JNI_FALSE); pCtx->GetResourceManager()->ReleaseResource(d3dsdo->pResource); d3dsdo->pResource = NULL; if (isRTT && isOpaque) { format = pCtx->GetPresentationParams()->BackBufferFormat; } else { format = D3DFMT_UNKNOWN; } res = pCtx->GetResourceManager()-> CreateTexture(d3dsdo->width, d3dsdo->height, isRTT, isOpaque, &format, 0/*usage*/, &d3dsdo->pResource); if (SUCCEEDED(res)) { J2dTraceLn1(J2D_TRACE_VERBOSE, " created texture pResource=%x", d3dsdo->pResource); d3dsdo->pResource->SetSDOps(d3dsdo); } else { D3DRQ_MarkLostIfNeeded(res, d3dsdo); } D3DSD_SetNativeDimensions(env, d3dsdo); return SUCCEEDED(res); }
HRESULT D3DResourceManager::GetBlitTexture(D3DResource **ppTextureResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetBlitTexture"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppTextureResource, E_FAIL); HRESULT res = GetStockTextureResource(D3DC_BLIT_TILE_SIZE, D3DC_BLIT_TILE_SIZE, FALSE/*isRTT*/, FALSE/*isOpaque*/, NULL, D3DUSAGE_DYNAMIC, &pBlitTexture); *ppTextureResource = pBlitTexture; return res; }
/* * Class: sun_java2d_d3d_D3DGraphicsDevice * Method: getDeviceIdNative * Signature: (I)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_sun_java2d_d3d_D3DGraphicsDevice_getDeviceIdNative (JNIEnv *env, jclass d3dsdc, jint gdiScreen) { D3DPipelineManager *pMgr; UINT adapter; D3DADAPTER_IDENTIFIER9 aid; IDirect3D9 *pd3d9; J2dTraceLn(J2D_TRACE_INFO, "D3DGD_getDeviceIdNative"); pMgr = D3DPipelineManager::GetInstance(); RETURN_STATUS_IF_NULL(pMgr, NULL); pd3d9 = pMgr->GetD3DObject(); RETURN_STATUS_IF_NULL(pd3d9, NULL); adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen); if (FAILED(pd3d9->GetAdapterIdentifier(adapter, 0, &aid))) { return NULL; } // ('%d.' will take no more than 6+1 chars since we are printing a WORD) // AAAA&BBBB MAX_DEVICE_IDENTIFIER_STRING (%d.%d.%d.%d)0 size_t len = (4+1+4 +1+MAX_DEVICE_IDENTIFIER_STRING+1 +1+(6+1)*4+1 +1); WCHAR *pAdapterId = new WCHAR[len]; RETURN_STATUS_IF_NULL(pAdapterId, NULL); _snwprintf(pAdapterId, len, L"%x&%x %S (%d.%d.%d.%d)", 0xffff & aid.VendorId, 0xffff & aid.DeviceId, aid.Description, HIWORD(aid.DriverVersion.HighPart), LOWORD(aid.DriverVersion.HighPart), HIWORD(aid.DriverVersion.LowPart), LOWORD(aid.DriverVersion.LowPart)); // _snwprintf doesn't add 0 at the end if the formatted string didn't fit // in the buffer so we have to make sure it is null terminated pAdapterId[len-1] = (WCHAR)0; J2dTraceLn1(J2D_TRACE_VERBOSE, " id=%S", pAdapterId); jstring ret = JNU_NewStringPlatform(env, pAdapterId); delete pAdapterId; return ret; }
/** * Enables the LCD text shader and updates any related state, such as the * gamma values. */ static HRESULT D3DTR_EnableLCDGlyphModeState(D3DContext *d3dc, D3DSDOps *dstOps, jboolean useCache, jint contrast) { D3DResource *pGlyphTexRes, *pCachedDestTexRes; IDirect3DTexture9 *pGlyphTex, *pCachedDestTex; RETURN_STATUS_IF_NULL(dstOps->pResource, E_FAIL); HRESULT res = S_OK; if (useCache) { // glyph cache had been already initialized pGlyphTexRes = d3dc->GetLCDGlyphCache()->GetGlyphCacheTexture(); } else { res = d3dc->GetResourceManager()->GetBlitTexture(&pGlyphTexRes); } RETURN_STATUS_IF_FAILED(res); pGlyphTex = pGlyphTexRes->GetTexture(); res = d3dc->GetResourceManager()-> GetCachedDestTexture(dstOps->pResource->GetDesc()->Format, &pCachedDestTexRes); RETURN_STATUS_IF_FAILED(res); pCachedDestTex = pCachedDestTexRes->GetTexture(); IDirect3DDevice9 *pd3dDevice = d3dc->Get3DDevice(); D3DTEXTUREFILTERTYPE fhint = d3dc->IsTextureFilteringSupported(D3DTEXF_NONE) ? D3DTEXF_NONE : D3DTEXF_POINT; pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, fhint); pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, fhint); pd3dDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, fhint); pd3dDevice->SetSamplerState(1, D3DSAMP_MINFILTER, fhint); d3dc->UpdateTextureColorState(D3DTA_TEXTURE, 1); // bind the texture containing glyph data to texture unit 0 d3dc->SetTexture(pGlyphTex, 0); // bind the texture tile containing destination data to texture unit 1 d3dc->SetTexture(pCachedDestTex, 1); // create/enable the LCD text shader res = d3dc->EnableLCDTextProgram(); RETURN_STATUS_IF_FAILED(res); // update the current contrast settings (note: these change very rarely, // but it seems that D3D pixel shader registers aren't maintained as // part of the pixel shader instance, so we need to update these // everytime around in case another shader blew away the contents // of those registers) D3DTR_UpdateLCDTextContrast(d3dc, contrast); // update the current color settings return D3DTR_UpdateLCDTextColor(d3dc, contrast); }
/* * Class: sun_java2d_d3d_D3DGraphicsDevice * Method: enterFullScreenExclusiveNative * Signature: (IJ)V */ JNIEXPORT jboolean JNICALL Java_sun_java2d_d3d_D3DGraphicsDevice_enterFullScreenExclusiveNative (JNIEnv *env, jclass gdc, jint gdiScreen, jlong window) { HRESULT res; D3DPipelineManager *pMgr; D3DContext *pCtx; HWND hWnd; AwtWindow *w; D3DPRESENT_PARAMETERS newParams, *pCurParams; D3DDISPLAYMODE dm; UINT adapter; J2dTraceLn(J2D_TRACE_INFO, "D3DGD_enterFullScreenExclusiveNative"); RETURN_STATUS_IF_NULL(pMgr = D3DPipelineManager::GetInstance(), JNI_FALSE); adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen); if (FAILED(res = pMgr->GetD3DContext(adapter, &pCtx))) { D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination()); return JNI_FALSE; } w = (AwtWindow *)AwtComponent::GetComponent((HWND)window); if (w == NULL || !::IsWindow(hWnd = w->GetTopLevelHWnd())) { J2dTraceLn(J2D_TRACE_WARNING, "D3DGD_enterFullScreenExclusiveNative: disposed window"); return JNI_FALSE; } // REMIND: should we also move the non-topleve window from // being on top here (it's moved to front in GraphicsDevice.setFSW())? pCtx->Get3DObject()->GetAdapterDisplayMode(adapter, &dm); pCurParams = pCtx->GetPresentationParams(); // let the mananger know that we're entering the fs mode, it will // set the proper current focus window for us, which ConfigureContext will // use when creating the device pMgr->SetFSFocusWindow(adapter, hWnd); newParams = *pCurParams; newParams.hDeviceWindow = hWnd; newParams.Windowed = FALSE; newParams.BackBufferCount = 1; newParams.BackBufferFormat = dm.Format; newParams.FullScreen_RefreshRateInHz = dm.RefreshRate; newParams.BackBufferWidth = dm.Width; newParams.BackBufferHeight = dm.Height; newParams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; newParams.SwapEffect = D3DSWAPEFFECT_DISCARD; res = pCtx->ConfigureContext(&newParams); D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination()); return SUCCEEDED(res); }
HRESULT D3DVertexCacher::Init(D3DContext *pCtx) { D3DCAPS9 caps; RETURN_STATUS_IF_NULL(pCtx, E_FAIL); ReleaseDefPoolResources(); this->pCtx = pCtx; firstPendingBatch = 0; firstPendingVertex = 0; firstUnusedVertex = 0; currentBatch = 0; ZeroMemory(vertices, sizeof(vertices)); ZeroMemory(batches, sizeof(batches)); lpD3DDevice = pCtx->Get3DDevice(); RETURN_STATUS_IF_NULL(lpD3DDevice, E_FAIL); ZeroMemory(&caps, sizeof(caps)); lpD3DDevice->GetDeviceCaps(&caps); D3DPOOL pool = (caps.DeviceType == D3DDEVTYPE_HAL) ? D3DPOOL_DEFAULT : D3DPOOL_SYSTEMMEM; // usage depends on whether we use hw or sw vertex processing HRESULT res = lpD3DDevice->CreateVertexBuffer(MAX_BATCH_SIZE*sizeof(J2DLVERTEX), D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, D3DFVF_J2DLVERTEX, pool, &lpD3DVertexBuffer, NULL); RETURN_STATUS_IF_FAILED(res); res = lpD3DDevice->SetStreamSource(0, lpD3DVertexBuffer, 0, sizeof(J2DLVERTEX)); RETURN_STATUS_IF_FAILED(res); lpD3DDevice->SetFVF(D3DFVF_J2DLVERTEX); return res; }
HRESULT D3DBufImgOps_DisableConvolveOp(D3DContext *d3dc) { IDirect3DDevice9 *pd3dDevice; J2dTraceLn(J2D_TRACE_INFO, "D3DBufImgOps_DisableConvolveOp"); RETURN_STATUS_IF_NULL(d3dc, E_FAIL); d3dc->UpdateState(STATE_CHANGE); // disable the ConvolveOp shader pd3dDevice = d3dc->Get3DDevice(); return pd3dDevice->SetPixelShader(NULL); }
/* * Class: sun_java2d_d3d_D3DSurfaceData * Method: getNativeResourceNative * Signature: (JI)J */ JNIEXPORT jlong JNICALL Java_sun_java2d_d3d_D3DSurfaceData_getNativeResourceNative (JNIEnv *env, jclass d3sdc, jlong pData, jint resType) { D3DSDOps *d3dsdo; J2dTraceLn(J2D_TRACE_INFO, "D3DSurfaceData_getNativeResourceNative") RETURN_STATUS_IF_NULL(d3dsdo = (D3DSDOps *)jlong_to_ptr(pData), 0L); if (resType == D3D_DEVICE_RESOURCE) { HRESULT res; D3DPipelineManager *pMgr; D3DContext *pCtx; RETURN_STATUS_IF_NULL(pMgr = D3DPipelineManager::GetInstance(), 0L); if (FAILED(res = pMgr->GetD3DContext(d3dsdo->adapter, &pCtx))) { D3DRQ_MarkLostIfNeeded(res, d3dsdo); return 0L; } return ptr_to_jlong(pCtx->Get3DDevice()); } RETURN_STATUS_IF_NULL(d3dsdo->pResource, 0L); if (resType == RT_PLAIN || resType == RT_TEXTURE) { return ptr_to_jlong(d3dsdo->pResource->GetSurface()); } if (resType == TEXTURE) { return ptr_to_jlong(d3dsdo->pResource->GetTexture()); } if (resType == FLIP_BACKBUFFER) { return ptr_to_jlong(d3dsdo->pResource->GetSwapChain()); } return 0L; }
HRESULT D3DResourceManager::GetBlitRTTexture(UINT width, UINT height, D3DFORMAT format, D3DResource **ppTextureResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetBlitRTTexture"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppTextureResource, E_FAIL); HRESULT res = GetStockTextureResource(width, height, TRUE/*isRTT*/, FALSE/*isOpaque*/, &format, 0, &pBlitRTTexture); if (SUCCEEDED(res)) { D3DSURFACE_DESC *pDesc = pBlitRTTexture->GetDesc(); D3DCAPS9 *pDevCaps = pCtx->GetDeviceCaps(); if ((width <= pDesc->Width && height <= pDesc->Height) && (format == pDesc->Format || SUCCEEDED(pCtx->Get3DObject()->CheckDeviceFormatConversion( pDevCaps->AdapterOrdinal, pDevCaps->DeviceType, format, pDesc->Format)))) { *ppTextureResource = pBlitRTTexture; return res; } // current texture doesn't fit, release and allocate a new one ReleaseResource(pBlitRTTexture); pBlitRTTexture = NULL; } if (width < D3DC_BLIT_TILE_SIZE) width = D3DC_BLIT_TILE_SIZE; if (height < D3DC_BLIT_TILE_SIZE) height = D3DC_BLIT_TILE_SIZE; res = CreateTexture(width, height, TRUE, FALSE, &format, 0,&pBlitRTTexture); *ppTextureResource = pBlitRTTexture; return res; }
HRESULT D3DGlyphCache::Init(D3DContext *pCtx) { D3DFORMAT format; RETURN_STATUS_IF_NULL(pCtx, E_FAIL); J2dTraceLn1(J2D_TRACE_INFO, "D3DGlyphCache::Init pCtx=%x", pCtx); this->pCtx = pCtx; if (pGlyphCache == NULL) { // init glyph cache data structure pGlyphCache = AccelGlyphCache_Init(D3DTR_CACHE_WIDTH, D3DTR_CACHE_HEIGHT, D3DTR_CACHE_CELL_WIDTH, D3DTR_CACHE_CELL_HEIGHT, D3DGlyphCache_FlushGlyphVertexCache); if (pGlyphCache == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "D3DGlyphCache::Init: "\ "could not init D3D glyph cache"); return E_FAIL; } } if (gcType == CACHE_GRAY) { format = pCtx->IsTextureFormatSupported(D3DFMT_A8) ? D3DFMT_A8 : D3DFMT_A8R8G8B8; } else { // gcType == CACHE_LCD format = pCtx->IsTextureFormatSupported(D3DFMT_R8G8B8) ? D3DFMT_R8G8B8 : D3DFMT_A8R8G8B8; } HRESULT res = pCtx->GetResourceManager()-> CreateTexture(D3DTR_CACHE_WIDTH, D3DTR_CACHE_HEIGHT, FALSE/*isRTT*/, FALSE/*isOpaque*/, &format, 0/*usage*/, &pGlyphCacheRes); if (FAILED(res)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "D3DGlyphCache::Init: "\ "could not create glyph cache texture"); } return res; }
HRESULT D3DBufImgOps_DisableLookupOp(D3DContext *d3dc) { IDirect3DDevice9 *pd3dDevice; J2dTraceLn(J2D_TRACE_INFO, "D3DBufImgOps_DisableLookupOp"); RETURN_STATUS_IF_NULL(d3dc, E_FAIL); d3dc->UpdateState(STATE_CHANGE); // disable the LookupOp shader pd3dDevice = d3dc->Get3DDevice(); pd3dDevice->SetPixelShader(NULL); // disable the lookup table on texture unit 1 return d3dc->SetTexture(NULL, 1); }
static HRESULT D3DTR_DrawGrayscaleGlyphViaCache(D3DContext *d3dc, GlyphInfo *ginfo, jint x, jint y) { HRESULT res = S_OK; D3DGlyphCache *pGrayscaleGCache; CacheCellInfo *cell; GlyphCacheInfo *gcache; jfloat x1, y1, x2, y2; J2dTraceLn(J2D_TRACE_VERBOSE, "D3DTR_DrawGrayscaleGlyphViaCache"); if (glyphMode != MODE_USE_CACHE_GRAY) { D3DTR_DisableGlyphModeState(d3dc); res = d3dc->BeginScene(STATE_GLYPHOP); RETURN_STATUS_IF_FAILED(res); glyphMode = MODE_USE_CACHE_GRAY; } pGrayscaleGCache = d3dc->GetGrayscaleGlyphCache(); gcache = pGrayscaleGCache->GetGlyphCache(); cell = AccelGlyphCache_GetCellInfoForCache(ginfo, gcache); if (cell == NULL) { // attempt to add glyph to accelerated glyph cache res = pGrayscaleGCache->AddGlyph(ginfo); RETURN_STATUS_IF_FAILED(res); cell = AccelGlyphCache_GetCellInfoForCache(ginfo, gcache); RETURN_STATUS_IF_NULL(cell, E_FAIL); } cell->timesRendered++; x1 = (jfloat)x; y1 = (jfloat)y; x2 = x1 + ginfo->width; y2 = y1 + ginfo->height; return d3dc->pVCacher->DrawTexture(x1, y1, x2, y2, cell->tx1, cell->ty1, cell->tx2, cell->ty2); }
/* * Class: sun_java2d_d3d_D3DGraphicsDevice * Method: exitFullScreenExclusiveNative * Signature: (I)V */ JNIEXPORT jboolean JNICALL Java_sun_java2d_d3d_D3DGraphicsDevice_exitFullScreenExclusiveNative (JNIEnv *env, jclass gdc, jint gdiScreen) { HRESULT res; D3DPipelineManager *pMgr; D3DContext *pCtx; D3DPRESENT_PARAMETERS newParams, *pCurParams; UINT adapter; J2dTraceLn(J2D_TRACE_INFO, "D3DGD_exitFullScreenExclusiveNative"); RETURN_STATUS_IF_NULL(pMgr = D3DPipelineManager::GetInstance(), JNI_FALSE); adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen); if (FAILED(res = pMgr->GetD3DContext(adapter, &pCtx))) { D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination()); return JNI_FALSE; } pCurParams = pCtx->GetPresentationParams(); newParams = *pCurParams; // we're exiting fs, the device window can be 0 newParams.hDeviceWindow = 0; newParams.Windowed = TRUE; newParams.BackBufferFormat = D3DFMT_UNKNOWN; newParams.BackBufferCount = 1; newParams.FullScreen_RefreshRateInHz = 0; newParams.BackBufferWidth = 0; newParams.BackBufferHeight = 0; newParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; newParams.SwapEffect = D3DSWAPEFFECT_COPY; res = pCtx->ConfigureContext(&newParams); D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination()); // exited fs, update current focus window // note that we call this after this adapter exited fs mode so that // the rest of the adapters can be reset pMgr->SetFSFocusWindow(adapter, 0); return SUCCEEDED(res); }
/* * Class: sun_java2d_d3d_D3DGraphicsDevice * Method: isD3DAvailableOnDeviceNative * Signature: (I)Z */ JNIEXPORT jboolean JNICALL Java_sun_java2d_d3d_D3DGraphicsDevice_isD3DAvailableOnDeviceNative (JNIEnv *env, jclass gdc, jint gdiScreen) { HRESULT res; D3DPipelineManager *pMgr; D3DContext *pCtx; UINT adapter; J2dTraceLn(J2D_TRACE_INFO, "D3DGD_isD3DAvailableOnDeviceNative"); RETURN_STATUS_IF_NULL(pMgr = D3DPipelineManager::GetInstance(), JNI_FALSE); adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen); if (FAILED(res = pMgr->GetD3DContext(adapter, &pCtx))) { D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination()); return JNI_FALSE; } return JNI_TRUE; }
/* * Class: sun_java2d_d3d_D3DGraphicsDevice * Method: getDeviceCapsNative * Signature: (I)I */ JNIEXPORT jint JNICALL Java_sun_java2d_d3d_D3DGraphicsDevice_getDeviceCapsNative (JNIEnv *env, jclass d3dsdc, jint gdiScreen) { D3DPipelineManager *pMgr; D3DContext *pCtx; UINT adapter; J2dRlsTraceLn(J2D_TRACE_INFO, "D3DGD_getDeviceCapsNative"); pMgr = D3DPipelineManager::GetInstance(); RETURN_STATUS_IF_NULL(pMgr, CAPS_EMPTY); adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen); if (FAILED(pMgr->GetD3DContext(adapter, &pCtx))) { J2dRlsTraceLn1(J2D_TRACE_ERROR, "D3DGD_getDeviceCapsNative: device %d disabled", adapter); return CAPS_EMPTY; } return pCtx->GetContextCaps(); }
HRESULT D3DGlyphCache::AddGlyph(GlyphInfo *glyph) { HRESULT res = S_OK; RETURN_STATUS_IF_NULL(pGlyphCacheRes, E_FAIL); CacheCellInfo *cellInfo = AccelGlyphCache_AddGlyph(pGlyphCache, glyph); if (cellInfo != NULL) { jint pixelsTouchedL = 0, pixelsTouchedR = 0; // store glyph image in texture cell res = pCtx->UploadTileToTexture(pGlyphCacheRes, glyph->image, cellInfo->x, cellInfo->y, 0, 0, glyph->width, glyph->height, glyph->rowBytes, tileFormat, &pixelsTouchedL, &pixelsTouchedR); // LCD text rendering optimization: if the number of pixels touched on // the first or last column of the glyph image is less than 1/3 of the // height of the glyph we do not consider them touched. // See D3DTextRenderer.cpp:UpdateCachedDestination for more information. // The leftOff/rightOff are only used in LCD cache case. if (gcType == CACHE_LCD) { jint threshold = glyph->height/3; cellInfo->leftOff = pixelsTouchedL < threshold ? 1 : 0; cellInfo->rightOff = pixelsTouchedR < threshold ? -1 : 0; } else { cellInfo->leftOff = 0; cellInfo->rightOff = 0; } } return res; }
HRESULT D3DBufImgOps_EnableRescaleOp(D3DContext *d3dc, jboolean nonPremult, unsigned char *scaleFactors, unsigned char *offsets) { HRESULT res; IDirect3DDevice9 *pd3dDevice; jint flags = 0; J2dTraceLn(J2D_TRACE_INFO, "D3DBufImgOps_EnableRescaleOp"); RETURN_STATUS_IF_NULL(d3dc, E_FAIL); d3dc->UpdateState(STATE_CHANGE); // choose the appropriate shader, depending on the source image if (nonPremult) { flags |= RESCALE_NON_PREMULT; } // locate/enable the shader program for the given flags res = d3dc->EnableRescaleProgram(flags); RETURN_STATUS_IF_FAILED(res); // update the "uniform" scale factor values (note that the Java-level // dispatching code always passes down 4 values here, regardless of // the original source image type) pd3dDevice = d3dc->Get3DDevice(); pd3dDevice->SetPixelShaderConstantF(0, (float *)scaleFactors, 1); // update the "uniform" offset values (note that the Java-level // dispatching code always passes down 4 values here, and that the // offsets will have already been normalized to the range [0,1]) return pd3dDevice->SetPixelShaderConstantF(1, (float *)offsets, 1); }
HRESULT D3DTR_DrawGlyphList(D3DContext *d3dc, D3DSDOps *dstOps, jint totalGlyphs, jboolean usePositions, jboolean subPixPos, jboolean rgbOrder, jint lcdContrast, jfloat glyphListOrigX, jfloat glyphListOrigY, unsigned char *images, unsigned char *positions) { int glyphCounter; HRESULT res = S_OK; J2dTraceLn(J2D_TRACE_INFO, "D3DTR_DrawGlyphList"); RETURN_STATUS_IF_NULL(d3dc, E_FAIL); RETURN_STATUS_IF_NULL(d3dc->Get3DDevice(), E_FAIL); RETURN_STATUS_IF_NULL(dstOps, E_FAIL); RETURN_STATUS_IF_NULL(images, E_FAIL); if (usePositions) { RETURN_STATUS_IF_NULL(positions, E_FAIL); } glyphMode = MODE_NOT_INITED; isCachedDestValid = JNI_FALSE; for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) { jint x, y; jfloat glyphx, glyphy; jboolean grayscale; GlyphInfo *ginfo = (GlyphInfo *)jlong_to_ptr(NEXT_LONG(images)); if (ginfo == NULL) { // this shouldn't happen, but if it does we'll just break out... J2dRlsTraceLn(J2D_TRACE_ERROR, "D3DTR_DrawGlyphList: glyph info is null"); break; } grayscale = (ginfo->rowBytes == ginfo->width); if (usePositions) { jfloat posx = NEXT_FLOAT(positions); jfloat posy = NEXT_FLOAT(positions); glyphx = glyphListOrigX + posx + ginfo->topLeftX; glyphy = glyphListOrigY + posy + ginfo->topLeftY; FLOOR_ASSIGN(x, glyphx); FLOOR_ASSIGN(y, glyphy); } else { glyphx = glyphListOrigX + ginfo->topLeftX; glyphy = glyphListOrigY + ginfo->topLeftY; FLOOR_ASSIGN(x, glyphx); FLOOR_ASSIGN(y, glyphy); glyphListOrigX += ginfo->advanceX; glyphListOrigY += ginfo->advanceY; } if (ginfo->image == NULL) { continue; } if (grayscale) { // grayscale or monochrome glyph data if (ginfo->width <= D3DTR_CACHE_CELL_WIDTH && ginfo->height <= D3DTR_CACHE_CELL_HEIGHT && SUCCEEDED(d3dc->InitGrayscaleGlyphCache())) { res = D3DTR_DrawGrayscaleGlyphViaCache(d3dc, ginfo, x, y); } else { res = D3DTR_DrawGrayscaleGlyphNoCache(d3dc, ginfo, x, y); } } else { // LCD-optimized glyph data jint rowBytesOffset = 0; if (subPixPos) { jint frac = (jint)((glyphx - x) * 3); if (frac != 0) { rowBytesOffset = 3 - frac; x += 1; } } if (rowBytesOffset == 0 && ginfo->width <= D3DTR_CACHE_CELL_WIDTH && ginfo->height <= D3DTR_CACHE_CELL_HEIGHT && SUCCEEDED(d3dc->InitLCDGlyphCache())) { res = D3DTR_DrawLCDGlyphViaCache(d3dc, dstOps, ginfo, x, y, glyphCounter, totalGlyphs, rgbOrder, lcdContrast); } else { res = D3DTR_DrawLCDGlyphNoCache(d3dc, dstOps, ginfo, x, y, rowBytesOffset, rgbOrder, lcdContrast); } } if (FAILED(res)) { break; } } D3DTR_DisableGlyphModeState(d3dc); return res; }
static HRESULT D3DTR_DrawLCDGlyphNoCache(D3DContext *d3dc, D3DSDOps *dstOps, GlyphInfo *ginfo, jint x, jint y, jint rowBytesOffset, jboolean rgbOrder, jint contrast) { jfloat tx1, ty1, tx2, ty2; jfloat dx1, dy1, dx2, dy2; jfloat dtx1, dty1, dtx2, dty2; jint tw, th; jint sx, sy, sw, sh; jint cx1, cy1, cx2, cy2; jint x0; jint w = ginfo->width; jint h = ginfo->height; TileFormat tileFormat = rgbOrder ? TILEFMT_3BYTE_RGB : TILEFMT_3BYTE_BGR; IDirect3DDevice9 *pd3dDevice = d3dc->Get3DDevice(); D3DResource *pBlitTextureRes, *pCachedDestTextureRes; IDirect3DTexture9 *pBlitTexture; IDirect3DSurface9 *pCachedDestSurface, *pDst; HRESULT res; J2dTraceLn(J2D_TRACE_VERBOSE, "D3DTR_DrawLCDGlyphNoCache"); RETURN_STATUS_IF_NULL(dstOps->pResource, E_FAIL); RETURN_STATUS_IF_NULL(pDst = dstOps->pResource->GetSurface(), E_FAIL); res = d3dc->GetResourceManager()->GetBlitTexture(&pBlitTextureRes); RETURN_STATUS_IF_FAILED(res); res = d3dc->GetResourceManager()-> GetCachedDestTexture(dstOps->pResource->GetDesc()->Format, &pCachedDestTextureRes); RETURN_STATUS_IF_FAILED(res); pBlitTexture = pBlitTextureRes->GetTexture(); pCachedDestSurface = pCachedDestTextureRes->GetSurface(); if (glyphMode != MODE_NO_CACHE_LCD) { D3DTR_DisableGlyphModeState(d3dc); res = d3dc->BeginScene(STATE_TEXTUREOP); RETURN_STATUS_IF_FAILED(res); res = D3DTR_EnableLCDGlyphModeState(d3dc,dstOps, JNI_FALSE, contrast); RETURN_STATUS_IF_FAILED(res); glyphMode = MODE_NO_CACHE_LCD; } x0 = x; tx1 = 0.0f; ty1 = 0.0f; dtx1 = 0.0f; dty1 = 0.0f; tw = D3DTR_NOCACHE_TILE_SIZE; th = D3DTR_NOCACHE_TILE_SIZE; for (sy = 0; sy < h; sy += th, y += th) { x = x0; sh = ((sy + th) > h) ? (h - sy) : th; for (sx = 0; sx < w; sx += tw, x += tw) { sw = ((sx + tw) > w) ? (w - sx) : tw; // calculate the bounds of the tile to be copied from the // destination into the cached tile cx1 = x; cy1 = y; cx2 = cx1 + sw; cy2 = cy1 + sh; // need to clamp to the destination bounds, otherwise the // StretchRect() call may fail if (cx1 < 0) cx1 = 0; if (cy1 < 0) cy1 = 0; if (cx2 > dstOps->width) cx2 = dstOps->width; if (cy2 > dstOps->height) cy2 = dstOps->height; if (cx2 > cx1 && cy2 > cy1) { // copy LCD mask into glyph texture tile d3dc->UploadTileToTexture(pBlitTextureRes, ginfo->image+rowBytesOffset, 0, 0, sx, sy, sw, sh, ginfo->rowBytes, tileFormat); // update the lower-right glyph texture coordinates tx2 = ((jfloat)sw) / D3DC_BLIT_TILE_SIZE; ty2 = ((jfloat)sh) / D3DC_BLIT_TILE_SIZE; // calculate the actual destination vertices dx1 = (jfloat)x; dy1 = (jfloat)y; dx2 = dx1 + sw; dy2 = dy1 + sh; // copy destination into cached texture tile (the upper-left // corner of the destination region will be positioned at the // upper-left corner (0,0) of the texture) RECT srcRect = { cx1, cy1, cx2, cy2 }; RECT dstRect = { cx1-x, cy1-y, cx2-x, cy2-y }; pd3dDevice->StretchRect(pDst, &srcRect, pCachedDestSurface, &dstRect, D3DTEXF_NONE); // update the remaining destination texture coordinates dtx2 = ((jfloat)sw) / D3DTR_CACHED_DEST_WIDTH; dty2 = ((jfloat)sh) / D3DTR_CACHED_DEST_HEIGHT; // render composed texture to the destination surface res = d3dc->pVCacher->DrawTexture( dx1, dy1, dx2, dy2, tx1, ty1, tx2, ty2, dtx1, dty1, dtx2, dty2); // unfortunately we need to flush after each tile d3dc->FlushVertexQueue(); } } } return res; }
static HRESULT D3DTR_DrawLCDGlyphViaCache(D3DContext *d3dc, D3DSDOps *dstOps, GlyphInfo *ginfo, jint x, jint y, jint glyphIndex, jint totalGlyphs, jboolean rgbOrder, jint contrast) { HRESULT res; D3DGlyphCache *pLCDGCache; CacheCellInfo *cell; GlyphCacheInfo *gcache; jint dx1, dy1, dx2, dy2; jfloat dtx1, dty1, dtx2, dty2; J2dTraceLn(J2D_TRACE_VERBOSE, "D3DTR_DrawLCDGlyphViaCache"); // the glyph cache is initialized before this method is called pLCDGCache = d3dc->GetLCDGlyphCache(); if (glyphMode != MODE_USE_CACHE_LCD) { D3DTR_DisableGlyphModeState(d3dc); res = d3dc->BeginScene(STATE_TEXTUREOP); RETURN_STATUS_IF_FAILED(res); pLCDGCache->CheckGlyphCacheByteOrder(rgbOrder); res = D3DTR_EnableLCDGlyphModeState(d3dc, dstOps, JNI_TRUE, contrast); RETURN_STATUS_IF_FAILED(res); glyphMode = MODE_USE_CACHE_LCD; } gcache = pLCDGCache->GetGlyphCache(); cell = AccelGlyphCache_GetCellInfoForCache(ginfo, gcache); if (cell == NULL) { // attempt to add glyph to accelerated glyph cache res = pLCDGCache->AddGlyph(ginfo); RETURN_STATUS_IF_FAILED(res); // we'll just no-op in the rare case that the cell is NULL cell = AccelGlyphCache_GetCellInfoForCache(ginfo, gcache); RETURN_STATUS_IF_NULL(cell, E_FAIL); } cell->timesRendered++; // location of the glyph in the destination's coordinate space dx1 = x; dy1 = y; dx2 = dx1 + ginfo->width; dy2 = dy1 + ginfo->height; // copy destination into second cached texture, if necessary D3DTR_UpdateCachedDestination(d3dc, dstOps, ginfo, dx1, dy1, dx2, dy2, dx1 + cell->leftOff, // adjusted dx1 dx2 + cell->rightOff, // adjusted dx2 glyphIndex, totalGlyphs); // texture coordinates of the destination tile dtx1 = ((jfloat)(dx1 - cachedDestBounds.x1)) / D3DTR_CACHED_DEST_WIDTH; dty1 = ((jfloat)(dy1 - cachedDestBounds.y1)) / D3DTR_CACHED_DEST_HEIGHT; dtx2 = ((jfloat)(dx2 - cachedDestBounds.x1)) / D3DTR_CACHED_DEST_WIDTH; dty2 = ((jfloat)(dy2 - cachedDestBounds.y1)) / D3DTR_CACHED_DEST_HEIGHT; // render composed texture to the destination surface return d3dc->pVCacher->DrawTexture((jfloat)dx1, (jfloat)dy1, (jfloat)dx2, (jfloat)dy2, cell->tx1, cell->ty1, cell->tx2, cell->ty2, dtx1, dty1, dtx2, dty2); }