Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/java2d/d3d/D3DVertexCacher.cpp
32288 views
/*1* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "D3DPipeline.h"26#include "D3DVertexCacher.h"27#include "D3DPaints.h"2829#include "math.h"3031// non-texturized macros3233#define ADD_VERTEX_XYC(X, Y, VCOLOR) \34do { \35vertices[firstUnusedVertex].x = (X); \36vertices[firstUnusedVertex].y = (Y); \37vertices[firstUnusedVertex].color = (DWORD)(VCOLOR); \38firstUnusedVertex++; \39} while (0)4041#define ADD_LINE_XYC(X1, Y1, X2, Y2, VCOLOR) \42do { \43ADD_VERTEX_XYC(X1, Y1, VCOLOR); \44ADD_VERTEX_XYC(X2, Y2, VCOLOR); \45batches[currentBatch].pNum++; \46} while (0)4748#define ADD_LINE_SEG_XYC(X, Y, VCOLOR) \49do { \50ADD_VERTEX_XYC(X, Y, VCOLOR); \51batches[currentBatch].pNum++; \52} while (0)5354#define ADD_TRIANGLE_XYC(X1, Y1, X2, Y2, X3, Y3, VCOLOR) \55do { \56ADD_VERTEX_XYC(X1, Y1, VCOLOR); \57ADD_VERTEX_XYC(X2, Y2, VCOLOR); \58ADD_VERTEX_XYC(X3, Y3, VCOLOR); \59batches[currentBatch].pNum++; \60} while (0)6162// texturized macros6364#define ADD_VERTEX_XYUVC(X, Y, U1, V1, VCOLOR) \65do { \66vertices[firstUnusedVertex].x = (X); \67vertices[firstUnusedVertex].y = (Y); \68vertices[firstUnusedVertex].tu1 = (U1); \69vertices[firstUnusedVertex].tv1 = (V1); \70vertices[firstUnusedVertex].color = (DWORD)(VCOLOR); \71firstUnusedVertex++; \72} while (0)7374#define ADD_VERTEX_XYUVUVC(X, Y, U1, V1, U2, V2, VCOLOR) \75do { \76vertices[firstUnusedVertex].tu2 = (U2); \77vertices[firstUnusedVertex].tv2 = (V2); \78ADD_VERTEX_XYUVC(X, Y, U1, V1, VCOLOR); \79} while (0)8081#define ADD_TRIANGLE_XYUVC(X1, Y1, X2, Y2, X3, Y3, \82U1, V1, U2, V2, U3, V3, VCOLOR) \83do { \84ADD_VERTEX_XYUVC(X1, Y1, U1, V1, VCOLOR); \85ADD_VERTEX_XYUVC(X2, Y2, U2, V2, VCOLOR); \86ADD_VERTEX_XYUVC(X3, Y3, U3, V3, VCOLOR); \87batches[currentBatch].pNum++; \88} while (0)8990#define ADD_TRIANGLE_XYUVUVC(X1, Y1, X2, Y2, X3, Y3, \91U11, V11, U12, V12, U13, V13, \92U21, V21, U22, V22, U23, V23, \93VCOLOR) \94do { \95ADD_VERTEX_XYUVUVC(X1, Y1, U11, V11, U21, V21, VCOLOR); \96ADD_VERTEX_XYUVUVC(X2, Y2, U12, V12, U22, V22, VCOLOR); \97ADD_VERTEX_XYUVUVC(X3, Y3, U13, V13, U23, V23, VCOLOR); \98batches[currentBatch].pNum++; \99} while (0)100101// These are fudge factors for rendering lines found by experimenting.102// They are used to tweak the geometry such that the rendering (mostly) matches103// our software rendering on most hardware. The main goal was to pick the104// numbers such that the beginning and ending pixels of lines match.105#define LINE_FUDGE106// fudge factors107#ifdef LINE_FUDGE108109// Horiz/vertical110#define HV_FF1 ( 0.0f)111#define HV_FF2 ( 0.51f)112// For the record: value below (or larger) is required for Intel 855, but113// breaks Nvidia, ATI and Intel 965, and since the pipeline is disabled on114// 855 anyway we'll use 0.51f.115//#define HV_FF2 ( 0.5315f)116#define HV_FF3 (-0.2f)117// single pixel118#define SP_FF4 ( 0.3f)119120// diagonal, down121#define DD_FX1 (-0.1f)122#define DD_FY1 (-0.25f)123#define DD_FX2 ( 0.2f)124#define DD_FY2 ( 0.304f)125// For the record: with this value diagonal-down lines with Texture paint126// are a bit off on all chipsets but Intel 965. So instead we'll use127// .304f which makes it better for the rest, but at a price of a bit128// of pixel/texel shifting on 965G129//#define DD_FY2 ( 0.4f)130// diagonal, up131#define DU_FX1 (-0.1f)132#define DU_FY1 ( 0.4f)133#define DU_FX2 ( 0.3f)134#define DU_FY2 (-0.3f)135136#else137138#define HV_FF1 (0.0f)139#define HV_FF2 (0.0f)140#define HV_FF3 (0.0f)141#define SP_FF4 (0.0f)142143#define DD_FX1 (0.0f)144#define DD_FY1 (0.0f)145#define DD_FX2 (0.0f)146#define DD_FY2 (0.0f)147#define DU_FX1 (0.0f)148#define DU_FY1 (0.0f)149#define DU_FX2 (0.0f)150#define DU_FY2 (0.0f)151152#endif153154HRESULT155D3DVertexCacher::CreateInstance(D3DContext *pCtx, D3DVertexCacher **ppVC)156{157HRESULT res;158159J2dTraceLn(J2D_TRACE_INFO, "D3DVertexCacher::CreateInstance");160161*ppVC = new D3DVertexCacher();162if (FAILED(res = (*ppVC)->Init(pCtx))) {163delete *ppVC;164*ppVC = NULL;165}166return res;167}168169D3DVertexCacher::D3DVertexCacher()170{171lpD3DDevice = NULL;172lpD3DVertexBuffer = NULL;173}174175HRESULT176D3DVertexCacher::Init(D3DContext *pCtx)177{178D3DCAPS9 caps;179180RETURN_STATUS_IF_NULL(pCtx, E_FAIL);181182ReleaseDefPoolResources();183184this->pCtx = pCtx;185186firstPendingBatch = 0;187firstPendingVertex = 0;188firstUnusedVertex = 0;189currentBatch = 0;190ZeroMemory(vertices, sizeof(vertices));191ZeroMemory(batches, sizeof(batches));192193lpD3DDevice = pCtx->Get3DDevice();194RETURN_STATUS_IF_NULL(lpD3DDevice, E_FAIL);195196ZeroMemory(&caps, sizeof(caps));197lpD3DDevice->GetDeviceCaps(&caps);198199D3DPOOL pool = (caps.DeviceType == D3DDEVTYPE_HAL) ?200D3DPOOL_DEFAULT : D3DPOOL_SYSTEMMEM;201// usage depends on whether we use hw or sw vertex processing202HRESULT res =203lpD3DDevice->CreateVertexBuffer(MAX_BATCH_SIZE*sizeof(J2DLVERTEX),204D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, D3DFVF_J2DLVERTEX,205pool, &lpD3DVertexBuffer, NULL);206RETURN_STATUS_IF_FAILED(res);207208res = lpD3DDevice->SetStreamSource(0, lpD3DVertexBuffer, 0,209sizeof(J2DLVERTEX));210RETURN_STATUS_IF_FAILED(res);211212lpD3DDevice->SetFVF(D3DFVF_J2DLVERTEX);213return res;214}215216void217D3DVertexCacher::ReleaseDefPoolResources()218{219SAFE_RELEASE(lpD3DVertexBuffer);220pCtx = NULL;221}222223HRESULT D3DVertexCacher::DrawLine(int x1, int y1, int x2, int y2)224{225HRESULT res;226if (SUCCEEDED(res = EnsureCapacity(D3DPT_LINELIST, 1*2))) {227float fx1, fy1, fx2, fy2;228if (y1 == y2) {229// horizontal230fy1 = (float)y1+HV_FF1;231fy2 = fy1;232233if (x1 > x2) {234fx1 = (float)x2+HV_FF3;235fx2 = (float)x1+HV_FF2;236} else if (x1 < x2) {237fx1 = (float)x1+HV_FF3;238fx2 = (float)x2+HV_FF2;239} else {240// single point, offset a little so that a single241// pixel is rendered242fx1 = (float)x1-SP_FF4;243fy1 = (float)y1-SP_FF4;244fx2 = (float)x2+SP_FF4;245fy2 = (float)y2+SP_FF4;246}247} else if (x1 == x2) {248// vertical249fx1 = (float)x1+HV_FF1;250fx2 = fx1;251if (y1 > y2) {252fy1 = (float)y2+HV_FF3;253fy2 = (float)y1+HV_FF2;254} else {255fy1 = (float)y1+HV_FF3;256fy2 = (float)y2+HV_FF2;257}258} else {259// diagonal260if (x1 > x2 && y1 > y2) {261// ^262// \ case -> inverse263fx1 = (float)x2;264fy1 = (float)y2;265fx2 = (float)x1;266fy2 = (float)y1;267} else if (x1 > x2 && y2 > y1) {268// /269// v case - inverse270fx1 = (float)x2;271fy1 = (float)y2;272fx2 = (float)x1;273fy2 = (float)y1;274} else {275// \ ^276// v or / - leave as is277fx1 = (float)x1;278fy1 = (float)y1;279fx2 = (float)x2;280fy2 = (float)y2;281}282283if (fx2 > fx1 && fy2 > fy1) {284// \285// v286fx1 += DD_FX1;287fy1 += DD_FY1;288fx2 += DD_FX2;289fy2 += DD_FY2;290} else {291// ^292// /293fx1 += DU_FX1;294fy1 += DU_FY1;295fx2 += DU_FX2;296fy2 += DU_FY2;297}298}299ADD_LINE_XYC(fx1, fy1, fx2, fy2, color);300}301return res;302}303304HRESULT305D3DVertexCacher::DrawPoly(jint nPoints, jboolean isClosed,306jint transX, jint transY,307jint *xPoints, jint *yPoints)308{309HRESULT res;310jfloat mx = (jfloat)xPoints[0];311jfloat my = (jfloat)yPoints[0];312jboolean isEmpty = TRUE;313314if (nPoints == 0) {315return S_OK;316}317318if (isClosed &&319xPoints[nPoints - 1] == xPoints[0] &&320yPoints[nPoints - 1] == yPoints[0])321{322isClosed = FALSE;323}324325// npoints is exactly the number of vertices we need,326// possibly plus one (if the path is closed)327UINT reqVerts = nPoints * 1;328int i = 0;329do {330// leave room for one possible additional closing point331UINT vertsInBatch = min(MAX_BATCH_SIZE-1, max(2, reqVerts));332if (SUCCEEDED(res = EnsureCapacity(D3DPT_LINESTRIP, vertsInBatch+1))) {333reqVerts -= vertsInBatch;334do {335jfloat x = (jfloat)xPoints[i];336jfloat y = (jfloat)yPoints[i];337338isEmpty = isEmpty && (x == mx && y == my);339340ADD_LINE_SEG_XYC(x + transX, y + transY, color);341i++;342vertsInBatch--;343} while (vertsInBatch > 0);344// include the last point from the current batch into the next345if (reqVerts > 0) {346i--;347reqVerts++;348// loop continues349} else if (isClosed && !isEmpty) {350// if this was the last batch, see if the closing point is needed;351// note that we have left the room for it352ADD_LINE_SEG_XYC(mx + transX, my + transY, color);353// for clarity, the loop is ended anyway354break;355} else if (isEmpty || !isClosed) {356// - either we went nowhere, then change the last point357// so that a single pixel is rendered358// - or it's not empty and not closed - add another359// point because on some boards the last point is not rendered360mx = xPoints[nPoints-1] + transX +SP_FF4;361my = yPoints[nPoints-1] + transY +SP_FF4;362ADD_LINE_SEG_XYC(mx, my, color);363// for clarity364break;365}366}367} while (reqVerts > 0 && SUCCEEDED(res));368369return res;370}371372HRESULT373D3DVertexCacher::DrawScanlines(jint scanlineCount, jint *scanlines)374{375HRESULT res;376float x1, x2, y;377UINT reqVerts = scanlineCount*2/*vertices per line*/;378379if (scanlineCount == 0) {380return S_OK;381}382383do {384UINT vertsInBatch = min(2*(MAX_BATCH_SIZE/2), reqVerts);385if (SUCCEEDED(res = EnsureCapacity(D3DPT_LINELIST, vertsInBatch))) {386reqVerts -= vertsInBatch;387do {388x1 = ((float)*(scanlines++)) +HV_FF3;389x2 = ((float)*(scanlines++)) +HV_FF2;390y = ((float)*(scanlines++)) +HV_FF1;391ADD_LINE_XYC(x1, y, x2, y, color);392vertsInBatch -= 2;393} while (vertsInBatch > 0);394}395} while (reqVerts > 0 && SUCCEEDED(res));396return res;397}398399HRESULT400D3DVertexCacher::FillSpans(jint spanCount, jint *spans)401{402HRESULT res;403float x1, y1, x2, y2;404UINT reqVerts = spanCount*2*3/*vertices per span: two triangles*/;405406if (spanCount == 0) {407return S_OK;408}409410do {411UINT vertsInBatch = min(6*(MAX_BATCH_SIZE/6), reqVerts);412if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, vertsInBatch))) {413reqVerts -= vertsInBatch;414do {415x1 = ((float)*(spans++));416y1 = ((float)*(spans++));417x2 = ((float)*(spans++));418y2 = ((float)*(spans++));419420ADD_TRIANGLE_XYC(x1, y1, x2, y1, x1, y2, color);421ADD_TRIANGLE_XYC(x1, y2, x2, y1, x2, y2, color);422vertsInBatch -= 6;423} while (vertsInBatch > 0);424}425} while (reqVerts > 0 && SUCCEEDED(res));426427return res;428}429430HRESULT D3DVertexCacher::DrawRect(int x1, int y1, int x2, int y2)431{432HRESULT res;433434if ((x2 - x1) < 2 || (y2 - y1) < 2) {435return FillRect(x1, y1, x2+1, y2+1);436}437if (SUCCEEDED(res = EnsureCapacity(D3DPT_LINELIST, 4*2))) {438439float fx1 = (float)x1;440float fy1 = (float)y1;441float fx2 = (float)x2;442float fy2 = (float)y2;443444// horiz: top left - top right445ADD_LINE_XYC(fx1+HV_FF3, fy1+HV_FF1, fx2-1.0f+HV_FF2, fy1+HV_FF1,color);446// horiz: bottom left - bottom right447ADD_LINE_XYC(fx1+1.0f+HV_FF3, fy2+HV_FF1, fx2+HV_FF2, fy2+HV_FF1,color);448// vert : top right - bottom right449ADD_LINE_XYC(fx2+HV_FF1, fy1+HV_FF3, fx2+HV_FF1, fy2-1.0f+HV_FF2,color);450// vert : top left - bottom left451ADD_LINE_XYC(fx1+HV_FF1, fy1+1.0f+HV_FF3, fx1+HV_FF1, fy2+HV_FF2,color);452}453return res;454}455456HRESULT D3DVertexCacher::FillRect(int x1, int y1, int x2, int y2)457{458HRESULT res;459if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, 2*3))) {460float fx1 = (float)x1;461float fy1 = (float)y1;462float fx2 = (float)x2;463float fy2 = (float)y2;464ADD_TRIANGLE_XYUVC(fx1, fy1, fx2, fy1, fx1, fy2,4650.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,466color);467ADD_TRIANGLE_XYUVC(fx1, fy2, fx2, fy1, fx2, fy2,4680.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,469color);470}471return res;472}473474HRESULT D3DVertexCacher::FillParallelogram(float fx11, float fy11,475float dx21, float dy21,476float dx12, float dy12)477{478HRESULT res;479if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, 2*3))) {480// correct texel to pixel mapping; see D3DContext::SetTransform()481// for non-id tx case482if (pCtx->IsIdentityTx()) {483fx11 -= 0.5f;484fy11 -= 0.5f;485}486dx21 += fx11;487dy21 += fy11;488float fx22 = dx21 + dx12;489float fy22 = dy21 + dy12;490dx12 += fx11;491dy12 += fy11;492493ADD_TRIANGLE_XYUVC(fx11, fy11, dx21, dy21, dx12, dy12,4940.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,495color);496ADD_TRIANGLE_XYUVC(dx12, dy12, dx21, dy21, fx22, fy22,4970.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,498color);499}500return res;501}502503#define ADJUST_PGRAM(V, DV, DIM) \504do { \505if ((DV) >= 0) { \506(DIM) += (DV); \507} else { \508(DIM) -= (DV); \509(V) += (DV); \510} \511} while (0)512513// Invert the following transform:514// DeltaT(0, 0) == (0, 0)515// DeltaT(1, 0) == (DX1, DY1)516// DeltaT(0, 1) == (DX2, DY2)517// DeltaT(1, 1) == (DX1+DX2, DY1+DY2)518// TM00 = DX1, TM01 = DX2, (TM02 = X11)519// TM10 = DY1, TM11 = DY2, (TM12 = Y11)520// Determinant = TM00*TM11 - TM01*TM10521// = DX1*DY2 - DX2*DY1522// Inverse is:523// IM00 = TM11/det, IM01 = -TM01/det524// IM10 = -TM10/det, IM11 = TM00/det525// IM02 = (TM01 * TM12 - TM11 * TM02) / det,526// IM12 = (TM10 * TM02 - TM00 * TM12) / det,527528#define DECLARE_MATRIX(MAT) \529float MAT ## 00, MAT ## 01, MAT ## 02, MAT ## 10, MAT ## 11, MAT ## 12530531#define GET_INVERTED_MATRIX(MAT, X11, Y11, DX1, DY1, DX2, DY2, RET_CODE) \532do { \533float det = DX1*DY2 - DX2*DY1; \534if (det == 0) { \535RET_CODE; \536} \537MAT ## 00 = DY2/det; \538MAT ## 01 = -DX2/det; \539MAT ## 10 = -DY1/det; \540MAT ## 11 = DX1/det; \541MAT ## 02 = (DX2 * Y11 - DY2 * X11) / det; \542MAT ## 12 = (DY1 * X11 - DX1 * Y11) / det; \543} while (0)544545#define TRANSFORM(MAT, TX, TY, X, Y) \546do { \547TX = (X) * MAT ## 00 + (Y) * MAT ## 01 + MAT ## 02; \548TY = (X) * MAT ## 10 + (Y) * MAT ## 11 + MAT ## 12; \549} while (0)550551HRESULT D3DVertexCacher::FillParallelogramAA(float fx11, float fy11,552float dx21, float dy21,553float dx12, float dy12)554{555HRESULT res;556DECLARE_MATRIX(om);557558GET_INVERTED_MATRIX(om, fx11, fy11, dx21, dy21, dx12, dy12,559return D3D_OK);560561if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, 2*3))) {562float px = fx11, py = fy11;563float pw = 0.0f, ph = 0.0f;564ADJUST_PGRAM(px, dx21, pw);565ADJUST_PGRAM(py, dy21, ph);566ADJUST_PGRAM(px, dx12, pw);567ADJUST_PGRAM(py, dy12, ph);568float px1 = floor(px);569float py1 = floor(py);570float px2 = ceil(px + pw);571float py2 = ceil(py + ph);572float u11, v11, u12, v12, u21, v21, u22, v22;573TRANSFORM(om, u11, v11, px1, py1);574TRANSFORM(om, u21, v21, px2, py1);575TRANSFORM(om, u12, v12, px1, py2);576TRANSFORM(om, u22, v22, px2, py2);577ADD_TRIANGLE_XYUVUVC(px1, py1, px2, py1, px1, py2,578u11, v11, u21, v21, u12, v12,5795.0, 5.0, 6.0, 5.0, 5.0, 6.0,580color);581ADD_TRIANGLE_XYUVUVC(px1, py2, px2, py1, px2, py2,582u12, v12, u21, v21, u22, v22,5835.0, 6.0, 6.0, 5.0, 6.0, 6.0,584color);585}586return res;587}588589HRESULT D3DVertexCacher::DrawParallelogramAA(float ox11, float oy11,590float ox21, float oy21,591float ox12, float oy12,592float ix11, float iy11,593float ix21, float iy21,594float ix12, float iy12)595{596HRESULT res;597DECLARE_MATRIX(om);598DECLARE_MATRIX(im);599600GET_INVERTED_MATRIX(im, ix11, iy11, ix21, iy21, ix12, iy12,601// inner parallelogram is degenerate602// therefore it encloses no area603// fill outer604return FillParallelogramAA(ox11, oy11,605ox21, oy21,606ox12, oy12));607GET_INVERTED_MATRIX(om, ox11, oy11, ox21, oy21, ox12, oy12,608return D3D_OK);609610if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, 2*3))) {611float ox = ox11, oy = oy11;612float ow = 0.0f, oh = 0.0f;613ADJUST_PGRAM(ox, ox21, ow);614ADJUST_PGRAM(oy, oy21, oh);615ADJUST_PGRAM(ox, ox12, ow);616ADJUST_PGRAM(oy, oy12, oh);617float ox11 = floor(ox);618float oy11 = floor(oy);619float ox22 = ceil(ox + ow);620float oy22 = ceil(oy + oh);621float ou11, ov11, ou12, ov12, ou21, ov21, ou22, ov22;622TRANSFORM(om, ou11, ov11, ox11, oy11);623TRANSFORM(om, ou21, ov21, ox22, oy11);624TRANSFORM(om, ou12, ov12, ox11, oy22);625TRANSFORM(om, ou22, ov22, ox22, oy22);626float iu11, iv11, iu12, iv12, iu21, iv21, iu22, iv22;627TRANSFORM(im, iu11, iv11, ox11, oy11);628TRANSFORM(im, iu21, iv21, ox22, oy11);629TRANSFORM(im, iu12, iv12, ox11, oy22);630TRANSFORM(im, iu22, iv22, ox22, oy22);631ADD_TRIANGLE_XYUVUVC(ox11, oy11, ox22, oy11, ox11, oy22,632ou11, ov11, ou21, ov21, ou12, ov12,633iu11, iv11, iu21, iv21, iu12, iv12,634color);635ADD_TRIANGLE_XYUVUVC(ox11, oy22, ox22, oy11, ox22, oy22,636ou12, ov12, ou21, ov21, ou22, ov22,637iu12, iv12, iu21, iv21, iu22, iv22,638color);639}640return res;641}642643HRESULT644D3DVertexCacher::DrawTexture(float x1, float y1, float x2, float y2,645float u1, float v1, float u2, float v2)646{647HRESULT res;648if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, 2*3))) {649// correct texel to pixel mapping; see D3DContext::SetTransform()650// for non-id tx case651if (pCtx->IsIdentityTx()) {652x1 -= 0.5f;653y1 -= 0.5f;654x2 -= 0.5f;655y2 -= 0.5f;656}657658ADD_TRIANGLE_XYUVC(x1, y1, x2, y1, x1, y2,659u1, v1, u2, v1, u1, v2,660color);661ADD_TRIANGLE_XYUVC(x1, y2, x2, y1, x2, y2,662u1, v2, u2, v1, u2, v2,663color);664}665return res;666}667668HRESULT669D3DVertexCacher::DrawTexture(float x1, float y1, float x2, float y2,670float u11, float v11, float u12, float v12,671float u21, float v21, float u22, float v22)672{673HRESULT res;674if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, 2*3))) {675// correct texel to pixel mapping; see D3DContext::SetTransform()676// for non-id tx case677if (pCtx->IsIdentityTx()) {678x1 -= 0.5f;679y1 -= 0.5f;680x2 -= 0.5f;681y2 -= 0.5f;682}683684ADD_TRIANGLE_XYUVUVC(x1, y1, x2, y1, x1, y2,685u11, v11, u12, v11, u11, v12,686u21, v21, u22, v21, u21, v22,687color);688ADD_TRIANGLE_XYUVUVC(x1, y2, x2, y1, x2, y2,689u11, v12, u12, v11, u12, v12,690u21, v22, u22, v21, u22, v22,691color);692}693return res;694}695696HRESULT D3DVertexCacher::Render(int actionType)697{698J2DLVERTEX *lpVert;699HRESULT res;700DWORD dwLockFlags;701UINT pendingVertices = firstUnusedVertex - firstPendingVertex;702703// nothing to render704if (pendingVertices == 0) {705if (actionType == RESET_ACTION) {706firstPendingBatch = 0;707firstPendingVertex = 0;708firstUnusedVertex = 0;709currentBatch = 0;710}711return D3D_OK;712}713714if (firstPendingVertex == 0) {715// no data in the buffer yet, we don't care about716// vertex buffer's contents717dwLockFlags = D3DLOCK_DISCARD;718} else {719// append to the existing data in the vertex buffer720dwLockFlags = D3DLOCK_NOOVERWRITE;721}722723if (SUCCEEDED(res =724lpD3DVertexBuffer->Lock((UINT)firstPendingVertex*sizeof(J2DLVERTEX),725(UINT)pendingVertices*sizeof(J2DLVERTEX),726(void**)&lpVert, dwLockFlags)))727{728// copy only new vertices729memcpy((void *)lpVert,730(void *)(vertices + firstPendingVertex),731pendingVertices * sizeof(J2DLVERTEX));732res = lpD3DVertexBuffer->Unlock();733UINT currentVertex = firstPendingVertex;734UINT batchSize;735J2dTraceLn2(J2D_TRACE_VERBOSE,736"D3DVC::Render Starting flushing of %d vertices "\737"in %d batches",738pendingVertices,739(currentBatch - firstPendingBatch + 1));740741742for (UINT b = firstPendingBatch; b <= currentBatch; b++) {743D3DPRIMITIVETYPE pType = batches[b].pType;744UINT primCount = batches[b].pNum;745switch (pType) {746// the macro for adding a line segment adds one too many prims747case D3DPT_LINESTRIP: batchSize = primCount; primCount--; break;748case D3DPT_LINELIST: batchSize = primCount*2; break;749default: batchSize = primCount*3; break;750}751res = lpD3DDevice->DrawPrimitive(pType, currentVertex, primCount);752currentVertex += batchSize;753// init to something it can never be754batches[b].pType = (D3DPRIMITIVETYPE)0;755batches[b].pNum = 0;756}757} else {758DebugPrintD3DError(res, "Can't lock vertex buffer");759}760761// REMIND: may need to rethink what to do in case of an error,762// should we try to render them later?763if (actionType == RESET_ACTION) {764firstPendingBatch = 0;765firstPendingVertex = 0;766firstUnusedVertex = 0;767currentBatch = 0;768} else {769firstPendingBatch = currentBatch;770firstPendingVertex = firstUnusedVertex;771}772773return res;774}775776HRESULT D3DVertexCacher::EnsureCapacity(D3DPRIMITIVETYPE newPType, UINT vNum)777{778HRESULT res = D3D_OK;779if (vNum > MAX_BATCH_SIZE) {780// REMIND: need to define our own errors781return D3DERR_NOTAVAILABLE;782}783if ((firstUnusedVertex + vNum) > MAX_BATCH_SIZE) {784// if we can't fit new vertices in the vertex buffer,785// render whatever we have in the buffer and start786// from the beginning of the vertex buffer787J2dTraceLn2(J2D_TRACE_VERBOSE,788"D3DVC::EnsureCapacity exceeded capacity. "\789"current v: %d, requested vertices: %d\n",790firstUnusedVertex, vNum);791if (FAILED(res = Render(RESET_ACTION))) {792return res;793}794}795796J2dTraceLn5(J2D_TRACE_VERBOSE,797"D3DVC::EnsureCapacity current batch: %d "\798" batch.type=%d newType=%d vNum=%d firstUnusedV=%d",799currentBatch, batches[currentBatch].pType, newPType, vNum,800firstUnusedVertex);801// there should not be multiple linestrips in a batch,802// or they will be counted as a single line strip803if (batches[currentBatch].pType != newPType ||804batches[currentBatch].pType == D3DPT_LINESTRIP)805{806// if this is a first unused batch, use it807if (firstUnusedVertex == firstPendingVertex) {808// record the first batch and vertex scheduled for rendering809firstPendingBatch = currentBatch;810firstPendingVertex = firstUnusedVertex;811} else {812// otherwise go to the next batch813currentBatch++;814}815batches[currentBatch].pType = newPType;816batches[currentBatch].pNum = 0;817}818// firstUnusedVertex is updated when new vertices are added819// to the vertices array820821return res;822}823824825