1 /*
   2  * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <iostream>
  27 
  28 #include "D3DPipeline.h"
  29 #include "D3DContext.h"
  30 #include "D3DPipelineManager.h"
  31 #include "PassThroughVS.h"
  32 
  33 #include "com_sun_prism_d3d_D3DContext.h"
  34 #include "D3DLight.h"
  35 #include "D3DMesh.h"
  36 #include "D3DMeshView.h"
  37 #include "D3DPhongMaterial.h"
  38 using std::cout;
  39 using std::endl;
  40 /**
  41  * Note: this method assumes that r is different from a, b!
  42  */
  43 inline void D3DUtils_MatrixMultTransposed(D3DMATRIX& r, const D3DMATRIX& a, const D3DMATRIX& b) {
  44     for (int i=0; i<4; i++) {
  45         for (int j=0; j<4; j++) {
  46             float t = 0;
  47             for (int k=0; k<4; k++) {
  48                 // transpose on the fly
  49                 t += a.m[i][k] * b.m[k][j];
  50             }
  51             r.m[j][i] = t;
  52         }
  53     }
  54 }
  55 
  56 inline void D3DUtils_MatrixTransposed(D3DMATRIX& r, const D3DMATRIX& a) {
  57     for (int i=0; i<4; i++) {
  58         for (int j=0; j<4; j++) {
  59             r.m[j][i] = a.m[i][j];
  60         }
  61     }
  62 }
  63 
  64 inline void D3DUtils_SetIdentityMatrix(D3DMATRIX *m) {
  65     m->_12 = m->_13 = m->_14 = m->_21 = m->_23 = m->_24 = 0.0f;
  66     m->_31 = m->_32 = m->_34 = m->_41 = m->_42 = m->_43 = 0.0f;
  67     m->_11 = m->_22 = m->_33 = m->_44 = 1.0f;
  68 }
  69 
  70 // static
  71 HRESULT
  72 D3DContext::CreateInstance(IDirect3D9 *pd3d9, IDirect3D9Ex *pd3d9Ex, UINT adapter, D3DContext **ppCtx)
  73 {
  74     HRESULT res;
  75     *ppCtx = new D3DContext(pd3d9, pd3d9Ex, adapter);
  76     if (FAILED(res = (*ppCtx)->InitContext())) {
  77         delete *ppCtx;
  78         *ppCtx = NULL;
  79     }
  80     return res;
  81 }
  82 
  83 D3DContext::D3DContext(IDirect3D9 *pd3d, IDirect3D9Ex *pd3dEx, UINT adapter)
  84 {
  85     TraceLn(NWT_TRACE_INFO, "D3DContext::D3DContext");
  86     TraceLn1(NWT_TRACE_VERBOSE, "  pd3d=0x%x", pd3d);
  87     pd3dObject = pd3d;
  88     pd3dObjectEx = pd3dEx;
  89     pd3dDevice = NULL;
  90     pd3dDeviceEx = NULL;
  91     adapterOrdinal = adapter;
  92     defaulResourcePool = D3DPOOL_SYSTEMMEM;
  93 
  94     pResourceMgr = NULL;
  95 
  96     pPassThroughVS = NULL;
  97     pVertexDecl = NULL;
  98     pIndices = NULL;
  99     pVertexBufferRes = NULL;
 100 
 101     bBeginScenePending = FALSE;
 102     phongShader = NULL;
 103 
 104     ZeroMemory(&devCaps, sizeof(D3DCAPS9));
 105     ZeroMemory(&curParams, sizeof(curParams));
 106 }
 107 
 108 /**
 109  * This method releases context resources either from the default pool only
 110  * (basically from vram) or all of them, depending on the passed argument.
 111  *
 112  * Note that some resources are still not under ResourceManager control so we
 113  * have to handle them separately. Ideally we'd move every allocated resource
 114  * under RM control.
 115  *
 116  * The reason we have single method instead of a pair of methods (one for
 117  * default only and one for everything) is to reduce code duplication. It is
 118  * possible to call ReleaseDefPoolResources from ReleaseContextResources but
 119  * then we'd traverse the resources list twice (may not be a big deal).
 120  */
 121 void D3DContext::ReleaseContextResources(int releaseType)
 122 {
 123     TraceLn2(NWT_TRACE_INFO,
 124              "D3DContext::ReleaseContextResources: %d pd3dDevice = 0x%x",
 125              releaseType, pd3dDevice);
 126 
 127     if (releaseType != RELEASE_ALL && releaseType != RELEASE_DEFAULT) {
 128         TraceLn1(NWT_TRACE_ERROR,
 129                 "D3DContext::ReleaseContextResources unknown type: %d",
 130                 releaseType);
 131         return;
 132     }
 133 
 134     EndScene();
 135 
 136     if (releaseType == RELEASE_DEFAULT) {
 137         if (pVertexBufferRes != NULL && pVertexBufferRes->IsDefaultPool()) {
 138             // if VB is in the default pool it will be released by the RM
 139             pVertexBufferRes = NULL;
 140         }
 141         pResourceMgr->ReleaseDefPoolResources();
 142     } else if (releaseType == RELEASE_ALL){
 143         // will be released with the resource manager
 144         pVertexBufferRes = NULL;
 145         SAFE_RELEASE(pVertexDecl);
 146         SAFE_RELEASE(pIndices);
 147         SAFE_RELEASE(pPassThroughVS);
 148         SAFE_DELETE(pResourceMgr);
 149     }
 150 }
 151 
 152 D3DContext::~D3DContext() {}
 153 
 154 int D3DContext::release() {
 155 
 156     TraceLn2(NWT_TRACE_INFO,
 157                 "~D3DContext: pd3dDevice=0x%x, pd3dObject =0x%x",
 158                 pd3dDevice, pd3dObject);
 159     ReleaseContextResources(RELEASE_ALL);
 160     SAFE_RELEASE(pd3dDevice);
 161     SAFE_RELEASE(pd3dDeviceEx);
 162 
 163     if (phongShader) {
 164         delete phongShader;
 165         phongShader = NULL;
 166     }
 167 
 168     delete this;
 169     return 0;
 170 }
 171 
 172 /*
 173  * Class:     com_sun_prism_d3d_D3DContext
 174  * Method:    nCreateD3DMesh
 175  * Signature: (J)J
 176  */
 177 JNIEXPORT jlong JNICALL Java_com_sun_prism_d3d_D3DContext_nCreateD3DMesh
 178   (JNIEnv *env, jclass, jlong ctx)
 179 {
 180     TraceLn(NWT_TRACE_INFO, "D3DContext_nCreateD3DMesh");
 181     D3DContext *pCtx = (D3DContext*) jlong_to_ptr(ctx);
 182     RETURN_STATUS_IF_NULL(pCtx, 0L);
 183     
 184     D3DMesh *mesh = new D3DMesh(pCtx);
 185     return ptr_to_jlong(mesh);
 186 }
 187 
 188 /*
 189  * Class:     com_sun_prism_d3d_D3DContext
 190  * Method:    nReleaseD3DMesh
 191  * Signature: (JJ)V
 192  */
 193 JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nReleaseD3DMesh
 194   (JNIEnv *env, jclass, jlong ctx, jlong nativeMesh)
 195 {
 196     TraceLn(NWT_TRACE_INFO, "D3DContext_nReleaseD3DMesh");
 197     D3DMesh *mesh = (D3DMesh *) jlong_to_ptr(nativeMesh);
 198     if (mesh) {
 199         delete mesh;
 200     }
 201 }
 202 
 203 /*
 204  * Class:     com_sun_prism_d3d_D3DContext
 205  * Method:    nBuildNativeGeometryShort
 206  * Signature: (JJ[FI[SI)Z
 207  */
 208 JNIEXPORT jboolean JNICALL Java_com_sun_prism_d3d_D3DContext_nBuildNativeGeometryShort
 209   (JNIEnv *env, jclass, jlong ctx, jlong nativeMesh, jfloatArray vb, jint vbSize, jshortArray ib, jint ibSize)
 210 {
 211     TraceLn(NWT_TRACE_INFO, "D3DContext_nBuildNativeGeometryShort");
 212     D3DMesh *mesh = (D3DMesh *) jlong_to_ptr(nativeMesh);
 213     RETURN_STATUS_IF_NULL(mesh, JNI_FALSE);
 214 
 215     UINT vertexBufferSize = env->GetArrayLength(vb);
 216     float *vertexBuffer = (float *) (env->GetPrimitiveArrayCritical(vb, NULL));
 217     UINT indexBufferSize = env->GetArrayLength(ib);
 218     USHORT *indexBuffer = (USHORT *) (env->GetPrimitiveArrayCritical(ib, NULL));
 219 
 220     if (vbSize < 0 || ibSize < 0) {
 221         return JNI_FALSE;
 222     }
 223 
 224     UINT uvbSize = (UINT) vbSize;
 225     UINT uibSize = (UINT) ibSize;
 226     if (vertexBuffer == NULL || indexBuffer == NULL
 227             || uvbSize > vertexBufferSize || uibSize > indexBufferSize) {
 228         return JNI_FALSE;
 229     }
 230 
 231     boolean result = mesh->buildBuffers(vertexBuffer, uvbSize, indexBuffer, uibSize);
 232     env->ReleasePrimitiveArrayCritical(ib, indexBuffer, 0);
 233     env->ReleasePrimitiveArrayCritical(vb, vertexBuffer, 0);
 234 
 235     return result;
 236 }
 237 
 238 /*
 239  * Class:     com_sun_prism_d3d_D3DContext
 240  * Method:    nBuildNativeGeometryInt
 241  * Signature: (JJ[FI[II)Z
 242  */
 243 JNIEXPORT jboolean JNICALL Java_com_sun_prism_d3d_D3DContext_nBuildNativeGeometryInt
 244   (JNIEnv *env, jclass, jlong ctx, jlong nativeMesh, jfloatArray vb, jint vbSize, jintArray ib, jint ibSize)
 245 {
 246     TraceLn(NWT_TRACE_INFO, "D3DContext_nBuildNativeGeometryInt");
 247     D3DMesh *mesh = (D3DMesh *) jlong_to_ptr(nativeMesh);
 248     RETURN_STATUS_IF_NULL(mesh, JNI_FALSE);
 249 
 250     UINT vertexBufferSize = env->GetArrayLength(vb);
 251     float *vertexBuffer = (float *) (env->GetPrimitiveArrayCritical(vb, NULL));
 252     UINT indexBufferSize = env->GetArrayLength(ib);
 253     UINT *indexBuffer = (UINT *) (env->GetPrimitiveArrayCritical(ib, NULL));
 254 
 255     if (vbSize < 0 || ibSize < 0) {
 256         return JNI_FALSE;
 257     }
 258 
 259     UINT uvbSize = (UINT) vbSize;
 260     UINT uibSize = (UINT) ibSize;
 261     if (vertexBuffer == NULL || indexBuffer == NULL
 262             || uvbSize > vertexBufferSize || uibSize > indexBufferSize) {
 263         return JNI_FALSE;
 264     }
 265 
 266     boolean result = mesh->buildBuffers(vertexBuffer, uvbSize, indexBuffer, uibSize);
 267     env->ReleasePrimitiveArrayCritical(ib, indexBuffer, 0);
 268     env->ReleasePrimitiveArrayCritical(vb, vertexBuffer, 0);
 269 
 270     return result;
 271 }
 272 
 273 /*
 274  * Class:     com_sun_prism_d3d_D3DContext
 275  * Method:    nCreateD3DPhongMaterial
 276  * Signature: (J)J
 277  */
 278 JNIEXPORT jlong JNICALL Java_com_sun_prism_d3d_D3DContext_nCreateD3DPhongMaterial
 279   (JNIEnv *env, jclass, jlong ctx)
 280 {
 281     TraceLn(NWT_TRACE_INFO, "D3DContext_nCreateD3DPhongMaterial");
 282     D3DContext *pCtx = (D3DContext*) jlong_to_ptr(ctx);
 283     RETURN_STATUS_IF_NULL(pCtx, 0L);
 284     
 285     D3DPhongMaterial *phongMaterial = new D3DPhongMaterial(pCtx);
 286     return ptr_to_jlong(phongMaterial);
 287 }
 288 
 289 /*
 290  * Class:     com_sun_prism_d3d_D3DContext
 291  * Method:    nReleaseD3DPhongMaterial
 292  * Signature: (JJ)V
 293  */
 294 JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nReleaseD3DPhongMaterial
 295   (JNIEnv *env, jclass, jlong ctx, jlong nativePhongMaterial)
 296 {
 297     TraceLn(NWT_TRACE_INFO, "D3DContext_nReleaseD3DPhongMaterial");
 298     D3DPhongMaterial *phongMaterial = (D3DPhongMaterial *) jlong_to_ptr(nativePhongMaterial);
 299     if (phongMaterial) {
 300         delete phongMaterial;
 301     }
 302 }
 303 
 304 /*
 305  * Class:     com_sun_prism_d3d_D3DContext
 306  * Method:    nSetSolidColor
 307  * Signature: (JJFFFF)V
 308  */
 309 JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nSetSolidColor
 310   (JNIEnv *env, jclass, jlong ctx, jlong nativePhongMaterial,
 311         jfloat r, jfloat g, jfloat b, jfloat a)
 312 {
 313     TraceLn(NWT_TRACE_INFO, "D3DContext_nSetSolidColor");
 314     D3DPhongMaterial *phongMaterial = (D3DPhongMaterial *) jlong_to_ptr(nativePhongMaterial);
 315     RETURN_IF_NULL(phongMaterial);
 316 
 317     phongMaterial->setSolidColor(r, g, b, a);
 318 }
 319 
 320 /*
 321  * Class:     com_sun_prism_d3d_D3DContext
 322  * Method:    nSetMap
 323  * Signature: (JJIJZZ)V
 324  */
 325 JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nSetMap
 326   (JNIEnv *env, jclass, jlong ctx, jlong nativePhongMaterial,
 327         jint mapType, jlong nativeTexture, jboolean isSpecularAlpha, jboolean isBumpAlpha)
 328 {
 329     TraceLn(NWT_TRACE_INFO, "D3DContext_nSetMap");
 330     D3DPhongMaterial *phongMaterial = (D3DPhongMaterial *) jlong_to_ptr(nativePhongMaterial);
 331     IDirect3DBaseTexture9 *texMap = (IDirect3DBaseTexture9 *)  jlong_to_ptr(nativeTexture);
 332     RETURN_IF_NULL(phongMaterial);
 333 
 334     phongMaterial->setMap(mapType, texMap, isSpecularAlpha ? true : false, isBumpAlpha ? true : false);
 335 }
 336 
 337 /*
 338  * Class:     com_sun_prism_d3d_D3DContext
 339  * Method:    nCreateD3DMeshView
 340  * Signature: (JJ)J
 341  */
 342 JNIEXPORT jlong JNICALL Java_com_sun_prism_d3d_D3DContext_nCreateD3DMeshView
 343   (JNIEnv *env, jclass, jlong ctx, jlong nativeMesh)
 344 {
 345     TraceLn(NWT_TRACE_INFO, "D3DContext_nCreateD3DMeshView");
 346     D3DContext *pCtx = (D3DContext*) jlong_to_ptr(ctx);
 347     RETURN_STATUS_IF_NULL(pCtx, 0L);
 348 
 349     D3DMesh *mesh = (D3DMesh *) jlong_to_ptr(nativeMesh);
 350     RETURN_STATUS_IF_NULL(mesh, 0L);
 351     
 352     D3DMeshView *meshView = new D3DMeshView(pCtx, mesh);
 353     return ptr_to_jlong(meshView);
 354 }
 355 
 356 /*
 357  * Class:     com_sun_prism_d3d_D3DContext
 358  * Method:    nReleaseD3DMeshView
 359  * Signature: (JJ)V
 360  */
 361 JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nReleaseD3DMeshView
 362   (JNIEnv *env, jclass, jlong ctx, jlong nativeMeshView)
 363 {
 364     TraceLn(NWT_TRACE_INFO, "D3DContext_nReleaseD3DMeshView");
 365     D3DMeshView *meshView = (D3DMeshView *) jlong_to_ptr(nativeMeshView);
 366     if (meshView) {
 367         delete meshView;
 368     }
 369 }
 370 
 371 /*
 372  * Class:     com_sun_prism_d3d_D3DContext
 373  * Method:    nSetCullingMode
 374  * Signature: (JJI)V
 375  */
 376 JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nSetCullingMode
 377   (JNIEnv *env, jclass, jlong ctx, jlong nativeMeshView, jint cullMode)
 378 {
 379     TraceLn(NWT_TRACE_INFO, "D3DContext_nSetCullingMode");
 380     D3DMeshView *meshView = (D3DMeshView *) jlong_to_ptr(nativeMeshView);
 381     RETURN_IF_NULL(meshView);
 382 
 383     switch (cullMode) {
 384         case com_sun_prism_d3d_D3DContext_CULL_BACK:
 385             cullMode = D3DCULL_CW;
 386             break;
 387         case com_sun_prism_d3d_D3DContext_CULL_FRONT:
 388             cullMode = D3DCULL_CCW;
 389             break;
 390         case com_sun_prism_d3d_D3DContext_CULL_NONE:
 391             cullMode = D3DCULL_NONE;
 392             break;
 393     }
 394     meshView->setCullingMode(cullMode);
 395 }
 396 
 397 /*
 398  * Class:     com_sun_prism_d3d_D3DContext
 399  * Method:    nBlit
 400  * Signature: (JJJIIIIIIII)V
 401  */
 402 JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nBlit
 403   (JNIEnv *env, jclass, jlong ctx, jlong nSrcRTT, jlong nDstRTT,
 404             jint srcX0, jint srcY0, jint srcX1, jint srcY1,
 405             jint dstX0, jint dstY0, jint dstX1, jint dstY1)
 406 {
 407     TraceLn(NWT_TRACE_INFO, "D3DContext_nBlit");
 408     D3DContext *pCtx = (D3DContext*) jlong_to_ptr(ctx);
 409     RETURN_IF_NULL(pCtx);
 410     
 411     D3DResource *srcRes = (D3DResource*) jlong_to_ptr(nSrcRTT);
 412     if (srcRes == NULL) {
 413         TraceLn(NWT_TRACE_INFO, "   error srcRes is NULL");
 414         return;
 415     }
 416     
 417     IDirect3DSurface9 *pSrcSurface = srcRes->GetSurface();
 418     if (pSrcSurface == NULL) {
 419         TraceLn(NWT_TRACE_INFO, "   error pSrcSurface is NULL");
 420         return;
 421     }
 422     
 423     D3DResource *dstRes = (D3DResource*) jlong_to_ptr(nDstRTT);
 424     IDirect3DSurface9 *pDstSurface = (dstRes == NULL) ? NULL : dstRes->GetSurface();
 425 
 426     pCtx->stretchRect(pSrcSurface, srcX0, srcY0, srcX1, srcY1,
 427                       pDstSurface, dstX0, dstY0, dstX1, dstY1);
 428 }
 429 
 430 /*
 431  * Class:     com_sun_prism_d3d_D3DContext
 432  * Method:    nSetMaterial
 433  * Signature: (JJJ)V
 434  */
 435 JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nSetMaterial
 436   (JNIEnv *env, jclass, jlong ctx, jlong nativeMeshView, jlong nativePhongMaterial)
 437 {
 438     TraceLn(NWT_TRACE_INFO, "D3DContext_nSetMaterial");
 439     D3DMeshView *meshView = (D3DMeshView *) jlong_to_ptr(nativeMeshView);
 440     RETURN_IF_NULL(meshView);
 441     
 442     D3DPhongMaterial *phongMaterial = (D3DPhongMaterial *) jlong_to_ptr(nativePhongMaterial);
 443     meshView->setMaterial(phongMaterial);
 444 }
 445 
 446 /*
 447  * Class:     com_sun_prism_d3d_D3DContext
 448  * Method:    nSetWireframe
 449  * Signature: (JJZ)V
 450  */
 451 JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nSetWireframe
 452   (JNIEnv *env, jclass, jlong ctx, jlong nativeMeshView, jboolean wireframe)
 453 {
 454     TraceLn(NWT_TRACE_INFO, "D3DContext_nSetWireframe");
 455     D3DMeshView *meshView = (D3DMeshView *) jlong_to_ptr(nativeMeshView);
 456     RETURN_IF_NULL(meshView);
 457 
 458     meshView->setWireframe(wireframe ? true : false);
 459 }
 460 
 461 /*
 462  * Class:     com_sun_prism_d3d_D3DContext
 463  * Method:    nSetAmbientLight
 464  * Signature: (JJFFF)V
 465  */
 466 JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nSetAmbientLight
 467   (JNIEnv *env, jclass, jlong ctx, jlong nativeMeshView,
 468         jfloat r, jfloat g, jfloat b)
 469 {
 470     TraceLn(NWT_TRACE_INFO, "D3DContext_nSetAmbientLight");
 471     D3DMeshView *meshView = (D3DMeshView *) jlong_to_ptr(nativeMeshView);
 472     RETURN_IF_NULL(meshView);
 473     
 474     meshView->setAmbientLight(r, g, b);
 475 }
 476 
 477 /*
 478  * Class:     com_sun_prism_d3d_D3DContext
 479  * Method:    nSetPointLight
 480  * Signature: (JJIFFFFFFF)V
 481  */
 482 JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nSetPointLight
 483   (JNIEnv *env, jclass, jlong ctx, jlong nativeMeshView, jint index,
 484         jfloat x, jfloat y, jfloat z, jfloat r, jfloat g, jfloat b, jfloat w)
 485 {
 486     TraceLn(NWT_TRACE_INFO, "D3DContext_nSetPointLight");
 487     D3DMeshView *meshView = (D3DMeshView *) jlong_to_ptr(nativeMeshView);
 488     RETURN_IF_NULL(meshView);
 489 
 490     meshView->setPointLight(index, x, y, z, r, g, b, w);
 491 }
 492 
 493 /*
 494  * Class:     com_sun_prism_d3d_D3DContext
 495  * Method:    nRenderMeshView
 496  * Signature: (JJ)V
 497  */
 498 JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nRenderMeshView
 499   (JNIEnv *env, jclass, jlong ctx, jlong nativeMeshView)
 500 {
 501     TraceLn(NWT_TRACE_INFO, "D3DContext_nRenderMeshView");
 502     D3DMeshView *meshView = (D3DMeshView *) jlong_to_ptr(nativeMeshView);
 503     RETURN_IF_NULL(meshView);
 504 
 505     meshView->render();
 506 }
 507 
 508 /*
 509  * Class:     com_sun_prism_d3d_D3DContext
 510  * Method:    nSetDeviceParametersFor2D
 511  */
 512 
 513 JNIEXPORT jint JNICALL Java_com_sun_prism_d3d_D3DContext_nSetDeviceParametersFor2D
 514   (JNIEnv *, jclass, jlong ctx)
 515 {
 516     TraceLn(NWT_TRACE_INFO, "D3DContext_nSetDeviceParametersFor2D");
 517     D3DContext *pCtx = (D3DContext*)jlong_to_ptr(ctx);
 518     RETURN_STATUS_IF_NULL(pCtx, S_FALSE);
 519     
 520     return pCtx->setDeviceParametersFor2D();
 521 }
 522 
 523 HRESULT D3DContext::setDeviceParametersFor2D() {
 524 
 525     RETURN_STATUS_IF_NULL(pd3dDevice, S_FALSE);
 526 
 527     HRESULT res = S_OK;
 528 
 529     IDirect3DVertexBuffer9 *vb = pVertexBufferRes->GetVertexBuffer();
 530 
 531     SUCCEEDED(res = pd3dDevice->SetVertexDeclaration(pVertexDecl)) &&
 532     SUCCEEDED(res = pd3dDevice->SetIndices(pIndices)) &&
 533     SUCCEEDED(res = pd3dDevice->SetVertexShader(pPassThroughVS)) &&
 534     SUCCEEDED(res = pd3dDevice->SetStreamSource(0, vb, 0, sizeof (PRISM_VERTEX_2D)));
 535 
 536     if (res == S_OK) {
 537         // Note: No need to restore blend and scissor states as the 2D states were
 538         //       invalidated on the Java side.
 539         SUCCEEDED(res = pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE)) &&
 540         SUCCEEDED(res = pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID)) &&
 541         SUCCEEDED(res = pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE));
 542     }
 543     return res;
 544 }
 545 
 546 /*
 547  * Class:     com_sun_prism_d3d_D3DContext
 548  * Method:    nSetDeviceParametersFor3D
 549  */
 550 
 551 JNIEXPORT jint JNICALL Java_com_sun_prism_d3d_D3DContext_nSetDeviceParametersFor3D
 552   (JNIEnv *, jclass, jlong ctx)
 553 {
 554     TraceLn(NWT_TRACE_INFO, "D3DContext_nSet3DVShaderAndVertexBuffer");
 555     D3DContext *pCtx = (D3DContext*)jlong_to_ptr(ctx);
 556     RETURN_STATUS_IF_NULL(pCtx, S_FALSE);
 557     
 558     return pCtx->setDeviceParametersFor3D();
 559 }
 560 
 561 HRESULT D3DContext::setDeviceParametersFor3D() {
 562     
 563     RETURN_STATUS_IF_NULL(pd3dDevice, S_FALSE);
 564 
 565     D3DMATRIX mat;
 566     HRESULT res = S_OK;
 567     float cPos[4];
 568 
 569     if (!phongShader) {
 570         phongShader = new D3DPhongShader(pd3dDevice);
 571     }
 572 
 573     D3DUtils_MatrixTransposed(mat, projection);
 574     cPos[0] = camPos.x;
 575     cPos[1] = camPos.y;
 576     cPos[2] = camPos.z;
 577     cPos[3] = 0;
 578 
 579 //    std::cout << "Camera Position: " << camPos.x << ", " << camPos.y << ", " << camPos.z << std::endl;
 580     // Use D3DPhongShader.h -- VSR_VIEWPROJMATRIX, VSR_CAMERAPOS
 581     SUCCEEDED(res = pd3dDevice->SetVertexShaderConstantF(VSR_VIEWPROJMATRIX, (float*) mat.m, 4)) &&
 582     SUCCEEDED(res = pd3dDevice->SetVertexShaderConstantF(VSR_CAMERAPOS, cPos, 1));
 583 
 584     // Reset 3D states
 585     state.wireframe = false;
 586     state.cullMode = D3DCULL_NONE;
 587     if (res == S_OK) {
 588         SUCCEEDED(res = pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE)) &&
 589         SUCCEEDED(res = pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID)) &&
 590         SUCCEEDED(res = pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE)) &&
 591         SUCCEEDED(res = pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO)) &&
 592         SUCCEEDED(res = pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE)) &&
 593         SUCCEEDED(res = pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE)) &&
 594         SUCCEEDED(res = pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE));
 595     }
 596     return res;
 597 }
 598 
 599 /*
 600  * Note: this method assumes that pIndices is not null
 601  */
 602 static HRESULT fillQuadIndices(IDirect3DIndexBuffer9 *pIndices, int maxQuads) {
 603     short * data = 0;
 604     HRESULT hr = pIndices->Lock(0, maxQuads * 6 * sizeof(short), (void **)&data, 0);
 605     if (SUCCEEDED(hr) && data) {
 606         for (int i = 0; i != maxQuads; ++i) {
 607             int vtx = i * 4;
 608             int idx = i * 6;
 609             data[idx + 0] = vtx + 0;
 610             data[idx + 1] = vtx + 1;
 611             data[idx + 2] = vtx + 2;
 612             data[idx + 3] = vtx + 2;
 613             data[idx + 4] = vtx + 1;
 614             data[idx + 5] = vtx + 3;
 615         }
 616         hr = pIndices->Unlock();
 617     }
 618     return hr;
 619 }
 620 
 621 HRESULT D3DContext::InitDevice(IDirect3DDevice9 *pd3dDevice)
 622 {
 623 #if defined PERF_COUNTERS
 624     stats.clear();
 625 #endif
 626 
 627     RETURN_STATUS_IF_NULL(pd3dDevice, S_FALSE);
 628 
 629     HRESULT res = S_OK;
 630 
 631     pd3dDevice->GetDeviceCaps(&devCaps);
 632 
 633     RlsTraceLn1(NWT_TRACE_INFO,
 634                    "D3DContext::InitDevice: device %d", adapterOrdinal);
 635 
 636     // disable some of the unneeded and costly d3d functionality
 637     pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
 638     pd3dDevice->SetRenderState(D3DRS_LIGHTING,  FALSE);
 639     pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
 640     pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_FALSE);
 641     pd3dDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE);
 642     pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
 643 
 644     // set clipping to true inorder support near and far clipping
 645     pd3dDevice->SetRenderState(D3DRS_CLIPPING,  TRUE);
 646 
 647     pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
 648     pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
 649     state.wireframe = false;
 650     state.cullMode = D3DCULL_NONE;
 651 
 652     if (pResourceMgr == NULL) {
 653         pResourceMgr = D3DResourceManager::CreateInstance(this);
 654     }
 655 
 656     D3DUtils_SetIdentityMatrix(&world);
 657     D3DUtils_SetIdentityMatrix(&projection);
 658     camPos.x = 0.0f;
 659     camPos.y = 0.0f;
 660     camPos.z = 0.0f;
 661 
 662     pixadjustx = pixadjusty = 0.0f;
 663 
 664     if (pVertexDecl == NULL) {
 665         res = pd3dDevice->CreateVertexDeclaration(PrismVDecl, &pVertexDecl);
 666         RETURN_STATUS_IF_FAILED(res);
 667     }
 668 //    res = pd3dDevice->SetVertexDeclaration(pVertexDecl);
 669 //    RETURN_STATUS_IF_FAILED(res);
 670 
 671     if (pIndices == NULL) {
 672         res = pd3dDevice->CreateIndexBuffer(sizeof(short) * 6 * MAX_BATCH_QUADS,
 673             D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, getResourcePool(), &pIndices, 0);
 674         if (pIndices) {
 675             res = fillQuadIndices(pIndices, MAX_BATCH_QUADS);
 676         }
 677         RETURN_STATUS_IF_FAILED(res);
 678     }
 679 //    res = pd3dDevice->SetIndices(pIndices);
 680 //    RETURN_STATUS_IF_FAILED(res);
 681 
 682     if (pPassThroughVS == NULL) {
 683         res = pd3dDevice->CreateVertexShader((DWORD*)g_vs30_passThrough, &pPassThroughVS);
 684         RETURN_STATUS_IF_FAILED(res);
 685     }
 686 //    res = pd3dDevice->SetVertexShader(pPassThroughVS);
 687 //    RETURN_STATUS_IF_FAILED(res);
 688 
 689     if (pVertexBufferRes == NULL) {
 690         res = GetResourceManager()->CreateVertexBuffer(&pVertexBufferRes);
 691         RETURN_STATUS_IF_FAILED(res);
 692     }
 693 //    res = pd3dDevice->SetStreamSource(0, pVertexBufferRes->GetVertexBuffer(),
 694 //                                      0, sizeof(PRISM_VERTEX_2D));
 695 //    RETURN_STATUS_IF_FAILED(res);
 696 
 697     bBeginScenePending = FALSE;
 698 
 699     RlsTraceLn1(NWT_TRACE_INFO,
 700                    "D3DContext::InitDevice: successfully initialized device %d",
 701                    adapterOrdinal);
 702 
 703     return res;
 704 }
 705 
 706 HRESULT
 707 D3DContext::TestCooperativeLevel()
 708 {
 709     TraceLn(NWT_TRACE_INFO, "D3DContext::testCooperativeLevel");
 710 
 711     RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
 712 
 713     HRESULT res = pd3dDevice->TestCooperativeLevel();
 714 
 715     switch (res) {
 716     case S_OK: break;
 717     case D3DERR_DEVICELOST:
 718         TraceLn1(NWT_TRACE_VERBOSE, "  device %d is still lost",
 719             adapterOrdinal);
 720         break;
 721     case D3DERR_DEVICENOTRESET:
 722         TraceLn1(NWT_TRACE_VERBOSE, "  device %d needs to be reset",
 723             adapterOrdinal);
 724         break;
 725     case E_FAIL:
 726         TraceLn(NWT_TRACE_VERBOSE, "  null device");
 727         break;
 728     default:
 729         TraceLn1(NWT_TRACE_ERROR, "D3DContext::testCooperativeLevel: "\
 730             "unknown error %x from TestCooperativeLevel", res);
 731     }
 732 
 733     return res;
 734 }
 735 
 736 HRESULT
 737 D3DContext::Clear(DWORD colorArgbPre, BOOL clearDepth, BOOL ignoreScissor)
 738 {
 739     RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
 740 
 741     HRESULT res;
 742     DWORD bSE = FALSE;
 743     DWORD bDE = FALSE;
 744     DWORD flags = D3DCLEAR_TARGET;
 745 
 746     if (ignoreScissor) {
 747         // scissor test affects Clear so it needs to be disabled first
 748         pd3dDevice->GetRenderState(D3DRS_SCISSORTESTENABLE, &bSE);
 749         if (bSE) {
 750             pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
 751         }
 752     }
 753     if (clearDepth) {
 754         // Must ensure that there is a depth buffer before attempting to clear it
 755         IDirect3DSurface9 *pCurrentDepth = NULL;
 756         pd3dDevice->GetDepthStencilSurface(&pCurrentDepth);
 757         clearDepth = pCurrentDepth == NULL ? FALSE : clearDepth;
 758         SAFE_RELEASE(pCurrentDepth);
 759     }
 760     if (clearDepth) {
 761         flags |= D3DCLEAR_ZBUFFER;
 762         // also make sure depth writes are enabled for the clear operation
 763         pd3dDevice->GetRenderState(D3DRS_ZWRITEENABLE, &bDE);
 764         if (!bDE) {
 765             pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_TRUE);
 766         }
 767     }
 768 
 769     res = pd3dDevice->Clear(0, NULL, flags, colorArgbPre, 1.0f, 0x0L);
 770 
 771     // restore previous state
 772     if (ignoreScissor && bSE) {
 773         pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
 774     }
 775     if (clearDepth && !bDE) {
 776         pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_FALSE);
 777     }
 778     return res;
 779 }
 780 
 781 BOOL D3DContext::IsDepthStencilBufferOk(D3DSURFACE_DESC *pTargetDesc, IDirect3DSurface9 *pTargetDepth)
 782 {
 783     TraceLn(NWT_TRACE_INFO, "D3DContext::IsDepthStencilBufferOk");
 784 
 785     RETURN_STATUS_IF_NULL(pTargetDepth, true);
 786     RETURN_STATUS_IF_NULL(pd3dDevice, false);
 787     RETURN_STATUS_IF_NULL(pd3dObject, false);
 788 
 789     D3DSURFACE_DESC descStencil;
 790     pTargetDepth->GetDesc(&descStencil);
 791 
 792     D3DDISPLAYMODE dm;
 793     return
 794         (SUCCEEDED(pd3dDevice->GetDisplayMode(0, &dm)) &&
 795          pTargetDesc->Width <= descStencil.Width &&
 796          pTargetDesc->Height <= descStencil.Height &&
 797          pTargetDesc->MultiSampleType == descStencil.MultiSampleType &&
 798          pTargetDesc->MultiSampleQuality == descStencil.MultiSampleQuality &&
 799          SUCCEEDED(pd3dObject->CheckDepthStencilMatch(
 800                adapterOrdinal,
 801                devCaps.DeviceType,
 802                dm.Format, pTargetDesc->Format,
 803                descStencil.Format)));
 804 }
 805 
 806 HRESULT
 807 D3DContext::InitDepthStencilBuffer(D3DSURFACE_DESC *pTargetDesc, IDirect3DSurface9 **ppDepthSSurface)
 808 {
 809     TraceLn(NWT_TRACE_INFO, "D3DContext::InitDepthStencilBuffer");
 810 
 811     RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
 812     RETURN_STATUS_IF_NULL(pTargetDesc, E_FAIL);
 813 
 814     HRESULT res;
 815     D3DDISPLAYMODE dm;
 816     if (FAILED(res = pd3dDevice->GetDisplayMode(0, &dm))) {
 817         return res;
 818     }
 819 
 820     D3DFORMAT newFormat =
 821         D3DPipelineManager::GetInstance()->GetMatchingDepthStencilFormat(
 822             adapterOrdinal, dm.Format, pTargetDesc->Format);
 823 
 824     res = pd3dDevice->CreateDepthStencilSurface(
 825         pTargetDesc->Width, pTargetDesc->Height, newFormat,
 826         pTargetDesc->MultiSampleType, pTargetDesc->MultiSampleQuality, false, ppDepthSSurface, 0);
 827 
 828     return res;
 829 }
 830 
 831 HRESULT
 832 D3DContext::UpdateVertexShaderTX()
 833 {
 834     TraceLn(NWT_TRACE_INFO, "D3DContext::UpdateVertexShaderTX");
 835 
 836     RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
 837 
 838     D3DMATRIX wvp;
 839     // create the WorldViewProj matrix
 840     // wvp = T(w * v * p);
 841     // since view is currently included in the projection matrix, wvp = T(w * p)
 842     D3DUtils_MatrixMultTransposed(wvp, world, projection);
 843     // Apply the pixel adjustment values for the current render target.
 844     // These values adjust our default (identity) coordinates so that the
 845     // pixel edges are at integer coordinate locations.
 846     wvp._14 += pixadjustx;
 847     wvp._24 += pixadjusty;
 848 
 849 //    fprintf(stderr, "UpdateVertexShaderTX:\n");
 850 //    fprintf(stderr, "  %5f %5f %5f %5f\n", wvp._11, wvp._12, wvp._13, wvp._14);
 851 //    fprintf(stderr, "  %5f %5f %5f %5f\n", wvp._21, wvp._22, wvp._23, wvp._24);
 852 //    fprintf(stderr, "  %5f %5f %5f %5f\n", wvp._31, wvp._32, wvp._33, wvp._34);
 853 //    fprintf(stderr, "  %5f %5f %5f %5f\n", wvp._41, wvp._42, wvp._43, wvp._44);
 854 
 855     return pd3dDevice->SetVertexShaderConstantF(0, (float*)wvp.m, 4);
 856 }
 857 
 858 HRESULT
 859 D3DContext::SetRenderTarget(IDirect3DSurface9 *pSurface,
 860         IDirect3DSurface9 **ppTargetDepthSurface,
 861         BOOL depthBuffer, BOOL msaa)
 862 {
 863     TraceLn1(NWT_TRACE_INFO,
 864                 "D3DContext::SetRenderTarget: pSurface=0x%x",
 865                 pSurface);
 866 
 867     RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
 868     RETURN_STATUS_IF_NULL(pSurface, E_FAIL);
 869 
 870     HRESULT res;
 871     D3DSURFACE_DESC descNew;
 872     IDirect3DSurface9 *pCurrentTarget;
 873     bool renderTargetChanged = false;
 874 
 875     pSurface->GetDesc(&descNew);
 876 
 877     if (SUCCEEDED(res = pd3dDevice->GetRenderTarget(0, &pCurrentTarget))) {
 878         if (pCurrentTarget != pSurface) {
 879             renderTargetChanged = true;
 880 #if defined PERF_COUNTERS
 881             getStats().numRenderTargetSwitch++;
 882 #endif
 883 
 884             if (FAILED(res = pd3dDevice->SetRenderTarget(0, pSurface))) {
 885                 DebugPrintD3DError(res, "D3DContext::SetRenderTarget: "\
 886                                         "error setting render target");
 887                 SAFE_RELEASE(pCurrentTarget);
 888                 return res;
 889             }
 890 
 891             currentSurface = pSurface;
 892         }
 893         SAFE_RELEASE(pCurrentTarget);
 894 
 895         IDirect3DSurface9 *pCurrentDepth;
 896         res = pd3dDevice->GetDepthStencilSurface(&pCurrentDepth);
 897         if (res == D3DERR_NOTFOUND) {
 898             pCurrentDepth = NULL;
 899             res = D3D_OK;
 900         } else if (FAILED(res)) {
 901             return res;
 902         }
 903 
 904         if (!IsDepthStencilBufferOk(&descNew, *ppTargetDepthSurface)) {
 905             *ppTargetDepthSurface = NULL;
 906         }
 907         bool depthIsNew = false;
 908         if (depthBuffer && (*ppTargetDepthSurface) == NULL) {
 909             if (FAILED(res = InitDepthStencilBuffer(&descNew, ppTargetDepthSurface))) {
 910                 DebugPrintD3DError(res, "D3DContext::SetRenderTarget: error creating new depth buffer");
 911                 return res;
 912             }
 913             depthIsNew = true;
 914         }
 915         if (pCurrentDepth != (*ppTargetDepthSurface)) {
 916             res = pd3dDevice->SetDepthStencilSurface(*ppTargetDepthSurface);
 917             if ((*ppTargetDepthSurface) != NULL && depthIsNew) {
 918                 // Depth buffer must be cleared after it is created, also
 919                 // if depth buffer was not attached when render target was
 920                 // cleared, then the depth buffer will contain garbage
 921                 pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_TRUE);
 922                 res = pd3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, NULL , 1.0f, 0x0L);
 923                 if (FAILED(res)) {
 924                     DebugPrintD3DError(res,
 925                             "D3DContext::SetRenderTarget: error clearing depth buffer");
 926                 }
 927             }
 928         } else if (!renderTargetChanged) {
 929             SAFE_RELEASE(pCurrentDepth);
 930             return res; // Render target has not changed
 931         }
 932         SAFE_RELEASE(pCurrentDepth);
 933         pd3dDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, msaa);
 934     }
 935     // NOTE PRISM: changed to only recalculate the matrix if current target is
 936     // different for now
 937 
 938     // we set the transform even if the render target didn't change;
 939     // this is because in some cases (fs mode) we use the default SwapChain of
 940     // the device, and its render target will be the same as the device's, and
 941     // we have to set the matrix correctly. This shouldn't be a performance
 942     // issue as render target changes are relatively rare
 943 
 944     // By default D3D has integer device coordinates at the center of pixels
 945     // but we want integer device coordinates to be at the edges of pixels.
 946     // Additionally, its default viewport is set so that coordinates on a
 947     // surface map onto (-1, +1) -> (+1, -1) as one moves from the upper left
 948     // corner to the lower right corner.  We need to move the values towards
 949     // -X and +Y by half a pixel using the following adjustment values:
 950     // half of (((+1) - (-1)) / dim), or half of (2 / dim) == (1 / dim).
 951     pixadjustx = -1.0f / descNew.Width;
 952     pixadjusty = +1.0f / descNew.Height;
 953     TraceLn1(NWT_TRACE_VERBOSE, "  current render target=0x%x", pSurface);
 954     TraceLn2(NWT_TRACE_VERBOSE, "      pixel adjustments=%f, %f", pixadjustx, pixadjusty);
 955     return res;
 956 }
 957 
 958 HRESULT
 959 D3DContext::SetCameraPosition(jdouble camPosX, jdouble camPosY, jdouble camPosZ)
 960 {
 961     TraceLn(NWT_TRACE_INFO, "D3DContext::SetCameraPosition");
 962 
 963     RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
 964     
 965     camPos.x = (float) camPosX;
 966     camPos.y = (float) camPosY;
 967     camPos.z = (float) camPosZ;
 968     return D3D_OK;
 969 }
 970 
 971 
 972 HRESULT
 973 D3DContext::SetProjViewMatrix(BOOL depthTest,
 974                               jdouble m00, jdouble m01, jdouble m02, jdouble m03,
 975                               jdouble m10, jdouble m11, jdouble m12, jdouble m13,
 976                               jdouble m20, jdouble m21, jdouble m22, jdouble m23,
 977                               jdouble m30, jdouble m31, jdouble m32, jdouble m33)
 978 {
 979     TraceLn(NWT_TRACE_INFO, "D3DContext::SetProjViewMatrix");
 980     TraceLn1(NWT_TRACE_VERBOSE, "  depthTest=%d", depthTest);
 981     
 982     RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
 983 
 984     projection._11 = (float)m00;    // Scale X
 985     projection._12 = (float)m10;    // Shear Y
 986     projection._13 = (float)m20;
 987     projection._14 = (float)m30;
 988 
 989     projection._21 = (float)m01;    // Shear X
 990     projection._22 = (float)m11;    // Scale Y
 991     projection._23 = (float)m21;
 992     projection._24 = (float)m31;
 993 
 994     projection._31 = (float)m02;
 995     projection._32 = (float)m12;
 996     projection._33 = (float)m22;
 997     projection._34 = (float)m32;
 998 
 999     projection._41 = (float)m03;    // Translate X
1000     projection._42 = (float)m13;    // Translate Y
1001     projection._43 = (float)m23;
1002     projection._44 = (float)m33;    // 1.0f;
1003 
1004     TraceLn4(NWT_TRACE_VERBOSE,
1005                 "  %5f %5f %5f %5f", projection._11, projection._12, projection._13, projection._14);
1006     TraceLn4(NWT_TRACE_VERBOSE,
1007                 "  %5f %5f %5f %5f", projection._21, projection._22, projection._23, projection._24);
1008     TraceLn4(NWT_TRACE_VERBOSE,
1009                 "  %5f %5f %5f %5f", projection._31, projection._32, projection._33, projection._34);
1010     TraceLn4(NWT_TRACE_VERBOSE,
1011                 "  %5f %5f %5f %5f", projection._41, projection._42, projection._43, projection._44);
1012 
1013 //    fprintf(stderr, "SetProjViewMatrix: depthTest =  %d\n", depthTest);
1014 //    fprintf(stderr, "  %5f %5f %5f %5f\n", projection._11, projection._12, projection._13, projection._14);
1015 //    fprintf(stderr, "  %5f %5f %5f %5f\n", projection._21, projection._22, projection._23, projection._24);
1016 //    fprintf(stderr, "  %5f %5f %5f %5f\n", projection._31, projection._32, projection._33, projection._34);
1017 //    fprintf(stderr, "  %5f %5f %5f %5f\n", projection._41, projection._42, projection._43, projection._44);
1018     if (depthTest) {
1019         pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1020         pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_TRUE);
1021         pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
1022 
1023         pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
1024         pd3dDevice->SetRenderState(D3DRS_ALPHAREF, 0x0);
1025         pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
1026     } else {
1027         pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
1028         pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_FALSE);
1029         pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE);
1030     }
1031 
1032     return D3D_OK;
1033 }
1034 
1035 void
1036 D3DContext::setWorldTransformIndentity() {
1037     TraceLn(NWT_TRACE_INFO, "D3DContext::setWorldTransformIndentity");
1038     
1039     RETURN_IF_NULL(pd3dDevice);
1040 
1041     D3DUtils_SetIdentityMatrix(&world);
1042 }
1043 
1044 void
1045 setWorldTx(D3DMATRIX &mat, jdouble m00, jdouble m01, jdouble m02, jdouble m03,
1046             jdouble m10, jdouble m11, jdouble m12, jdouble m13,
1047             jdouble m20, jdouble m21, jdouble m22, jdouble m23,
1048             jdouble m30, jdouble m31, jdouble m32, jdouble m33) {
1049 
1050     mat._11 = (float)m00;     // Scale X
1051     mat._12 = (float)m10;     // Shear Y
1052     mat._13 = (float)m20;
1053     mat._14 = (float)m30;
1054 
1055     mat._21 = (float)m01;    // Shear X
1056     mat._22 = (float)m11;    // Scale Y
1057     mat._23 = (float)m21;
1058     mat._24 = (float)m31;
1059 
1060     mat._31 = (float)m02;
1061     mat._32 = (float)m12;
1062     mat._33 = (float)m22;
1063     mat._34 = (float)m32;
1064 
1065     mat._41 = (float)m03;    // Translate X
1066     mat._42 = (float)m13;    // Translate Y
1067     mat._43 = (float)m23;
1068     mat._44 = (float)m33;    // 1.0f;
1069 
1070     TraceLn4(NWT_TRACE_VERBOSE,
1071                 "  %5f %5f %5f %5f", mat._11, mat._12, mat._13, mat._14);
1072     TraceLn4(NWT_TRACE_VERBOSE,
1073                 "  %5f %5f %5f %5f", mat._21, mat._22, mat._23, mat._24);
1074     TraceLn4(NWT_TRACE_VERBOSE,
1075                 "  %5f %5f %5f %5f", mat._31, mat._32, mat._33, mat._34);
1076     TraceLn4(NWT_TRACE_VERBOSE,
1077                 "  %5f %5f %5f %5f", mat._41, mat._42, mat._43, mat._44);
1078 
1079 //    fprintf(stderr, "World Matrix:\n");
1080 //    fprintf(stderr, "  %5f %5f %5f %5f\n", mat._11, mat._12, mat._13, mat._14);
1081 //    fprintf(stderr, "  %5f %5f %5f %5f\n", mat._21, mat._22, mat._23, mat._24);
1082 //    fprintf(stderr, "  %5f %5f %5f %5f\n", mat._31, mat._32, mat._33, mat._34);
1083 //    fprintf(stderr, "  %5f %5f %5f %5f\n", mat._41, mat._42, mat._43, mat._44);
1084 }
1085 
1086 void
1087 D3DContext::setWorldTransform(jdouble m00, jdouble m01, jdouble m02, jdouble m03,
1088             jdouble m10, jdouble m11, jdouble m12, jdouble m13,
1089             jdouble m20, jdouble m21, jdouble m22, jdouble m23,
1090             jdouble m30, jdouble m31, jdouble m32, jdouble m33) {
1091 
1092 //    std::cerr << "D3DContext::setWorldTransform" << std::endl;
1093     TraceLn(NWT_TRACE_INFO, "D3DContext::setWorldTransform");
1094     
1095     RETURN_IF_NULL(pd3dDevice);
1096     
1097     setWorldTx(world,
1098             m00, m01, m02, m03,
1099             m10, m11, m12, m13,
1100             m20, m21, m22, m23,
1101             m30, m31, m32, m33);
1102 }
1103 
1104 HRESULT
1105 D3DContext::ResetTransform()
1106 {
1107     TraceLn(NWT_TRACE_INFO, "D3DContext::ResetTransform");
1108 
1109     RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
1110 
1111     D3DUtils_SetIdentityMatrix(&world);
1112     return UpdateVertexShaderTX();
1113 }
1114 
1115 HRESULT
1116 D3DContext::SetTransform(jdouble m00, jdouble m01, jdouble m02, jdouble m03,
1117                          jdouble m10, jdouble m11, jdouble m12, jdouble m13,
1118                          jdouble m20, jdouble m21, jdouble m22, jdouble m23,
1119                          jdouble m30, jdouble m31, jdouble m32, jdouble m33)
1120 
1121 {
1122 
1123 //    std::cerr << "D3DContext::SetTransform" << std::endl;
1124     TraceLn(NWT_TRACE_INFO, "D3DContext::SetTransform");
1125     
1126     RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
1127     
1128     setWorldTx(world,
1129             m00, m01, m02, m03,
1130             m10, m11, m12, m13,
1131             m20, m21, m22, m23,
1132             m30, m31, m32, m33);
1133 
1134     return UpdateVertexShaderTX();
1135 }
1136 
1137 HRESULT
1138 D3DContext::SetRectClip(int x1, int y1, int x2, int y2)
1139 {
1140     TraceLn(NWT_TRACE_INFO, "D3DContext::SetRectClip");
1141     TraceLn4(NWT_TRACE_VERBOSE,
1142                 "  x1=%-4d y1=%-4d x2=%-4d y2=%-4d",
1143                 x1, y1, x2, y2);
1144 
1145     RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
1146 
1147     IDirect3DSurface9 *pCurrentTarget;
1148     HRESULT res = pd3dDevice->GetRenderTarget(0, &pCurrentTarget);
1149     RETURN_STATUS_IF_FAILED(res);
1150 
1151     D3DSURFACE_DESC desc;
1152     pCurrentTarget->GetDesc(&desc);
1153     SAFE_RELEASE(pCurrentTarget);
1154 
1155     if (x1 <= 0 && y1 <= 0 &&
1156         (UINT)x2 >= desc.Width && (UINT)y2 >= desc.Height)
1157     {
1158         TraceLn(NWT_TRACE_VERBOSE,
1159                    "  disabling clip (== render target dimensions)");
1160         return pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1161     }
1162 
1163     // clip to the dimensions of the target surface, otherwise
1164     // SetScissorRect will fail
1165     if (x1 < 0)                 x1 = 0;
1166     if (y1 < 0)                 y1 = 0;
1167     if ((UINT)x2 > desc.Width)  x2 = desc.Width;
1168     if ((UINT)y2 > desc.Height) y2 = desc.Height;
1169     if (x1 > x2)                x2 = x1 = 0;
1170     if (y1 > y2)                y2 = y1 = 0;
1171     RECT newRect = { x1, y1, x2, y2 };
1172     if (SUCCEEDED(res = pd3dDevice->SetScissorRect(&newRect))) {
1173         res = pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1174     } else {
1175         DebugPrintD3DError(res, "Error setting scissor rect");
1176         RlsTraceLn4(NWT_TRACE_ERROR,
1177                        "  x1=%-4d y1=%-4d x2=%-4d y2=%-4d",
1178                        x1, y1, x2, y2);
1179     }
1180 
1181     return res;
1182 }
1183 
1184 HRESULT
1185 D3DContext::ResetClip()
1186 {
1187     TraceLn(NWT_TRACE_INFO, "D3DContext::ResetClip");
1188 
1189     RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
1190     
1191     return pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1192 }
1193 
1194 HRESULT D3DContext::BeginScene()
1195 {
1196     RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
1197 
1198     if (!bBeginScenePending) {
1199         bBeginScenePending = TRUE;
1200         HRESULT res = pd3dDevice->BeginScene();
1201         TraceLn(NWT_TRACE_INFO, "D3DContext::BeginScene");
1202         return res;
1203     }
1204     return S_OK;
1205 }
1206 
1207 HRESULT D3DContext::EndScene()
1208 {
1209     if (bBeginScenePending) {
1210         bBeginScenePending = FALSE;
1211         TraceLn(NWT_TRACE_INFO, "D3DContext::EndScene");
1212         return pd3dDevice->EndScene();
1213     }
1214     return S_OK;
1215 }
1216 
1217 HRESULT D3DContext::InitContextCaps() {
1218     if (!IsPow2TexturesOnly()) {
1219         RlsTraceLn(NWT_TRACE_VERBOSE, "  CAPS_TEXNONPOW2");
1220     }
1221     if (!IsSquareTexturesOnly()) {
1222         RlsTraceLn(NWT_TRACE_VERBOSE, "  CAPS_TEXNONSQUARE");
1223     }
1224     return S_OK;
1225 }