ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

drawprim.c
Go to the documentation of this file.
00001 /*
00002  * WINED3D draw functions
00003  *
00004  * Copyright 2002-2004 Jason Edmeades
00005  * Copyright 2002-2004 Raphael Junqueira
00006  * Copyright 2004 Christian Costa
00007  * Copyright 2005 Oliver Stieber
00008  * Copyright 2006, 2008 Henri Verbeet
00009  * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
00010  * Copyright 2009 Henri Verbeet for CodeWeavers
00011  *
00012  * This library is free software; you can redistribute it and/or
00013  * modify it under the terms of the GNU Lesser General Public
00014  * License as published by the Free Software Foundation; either
00015  * version 2.1 of the License, or (at your option) any later version.
00016  *
00017  * This library is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020  * Lesser General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU Lesser General Public
00023  * License along with this library; if not, write to the Free Software
00024  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00025  */
00026 
00027 #include "config.h"
00028 #include "wined3d_private.h"
00029 
00030 WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
00031 
00032 #include <stdio.h>
00033 #include <math.h>
00034 
00035 /* GL locking is done by the caller */
00036 static void drawStridedFast(const struct wined3d_gl_info *gl_info, GLenum primitive_type, UINT count, UINT idx_size,
00037         const void *idx_data, UINT start_idx, INT base_vertex_index)
00038 {
00039     if (idx_size)
00040     {
00041         GLenum idxtype = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
00042         if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
00043         {
00044             GL_EXTCALL(glDrawElementsBaseVertex(primitive_type, count, idxtype,
00045                     (const char *)idx_data + (idx_size * start_idx), base_vertex_index));
00046             checkGLcall("glDrawElementsBaseVertex");
00047         }
00048         else
00049         {
00050             glDrawElements(primitive_type, count,
00051                     idxtype, (const char *)idx_data + (idx_size * start_idx));
00052             checkGLcall("glDrawElements");
00053         }
00054     }
00055     else
00056     {
00057         glDrawArrays(primitive_type, start_idx, count);
00058         checkGLcall("glDrawArrays");
00059     }
00060 }
00061 
00062 /*
00063  * Actually draw using the supplied information.
00064  * Slower GL version which extracts info about each vertex in turn
00065  */
00066 
00067 /* GL locking is done by the caller */
00068 static void drawStridedSlow(const struct wined3d_device *device, const struct wined3d_context *context,
00069         const struct wined3d_stream_info *si, UINT NumVertexes, GLenum glPrimType,
00070         const void *idxData, UINT idxSize, UINT startIdx)
00071 {
00072     unsigned int               textureNo    = 0;
00073     const WORD                *pIdxBufS     = NULL;
00074     const DWORD               *pIdxBufL     = NULL;
00075     UINT vx_index;
00076     const struct wined3d_state *state = &device->stateBlock->state;
00077     LONG SkipnStrides = startIdx;
00078     BOOL pixelShader = use_ps(state);
00079     BOOL specular_fog = FALSE;
00080     const BYTE *texCoords[WINED3DDP_MAXTEXCOORD];
00081     const BYTE *diffuse = NULL, *specular = NULL, *normal = NULL, *position = NULL;
00082     const struct wined3d_gl_info *gl_info = context->gl_info;
00083     UINT texture_stages = gl_info->limits.texture_stages;
00084     const struct wined3d_stream_info_element *element;
00085     UINT num_untracked_materials;
00086     DWORD tex_mask = 0;
00087 
00088     TRACE("Using slow vertex array code\n");
00089 
00090     /* Variable Initialization */
00091     if (idxSize)
00092     {
00093         /* Immediate mode drawing can't make use of indices in a vbo - get the
00094          * data from the index buffer. If the index buffer has no vbo (not
00095          * supported or other reason), or with user pointer drawing idxData
00096          * will be non-NULL. */
00097         if (!idxData)
00098             idxData = buffer_get_sysmem(state->index_buffer, gl_info);
00099 
00100         if (idxSize == 2) pIdxBufS = idxData;
00101         else pIdxBufL = idxData;
00102     } else if (idxData) {
00103         ERR("non-NULL idxData with 0 idxSize, this should never happen\n");
00104         return;
00105     }
00106 
00107     /* Start drawing in GL */
00108     glBegin(glPrimType);
00109 
00110     if (si->use_map & (1 << WINED3D_FFP_POSITION))
00111     {
00112         element = &si->elements[WINED3D_FFP_POSITION];
00113         position = element->data.addr;
00114     }
00115 
00116     if (si->use_map & (1 << WINED3D_FFP_NORMAL))
00117     {
00118         element = &si->elements[WINED3D_FFP_NORMAL];
00119         normal = element->data.addr;
00120     }
00121     else
00122     {
00123         glNormal3f(0, 0, 0);
00124     }
00125 
00126     num_untracked_materials = context->num_untracked_materials;
00127     if (si->use_map & (1 << WINED3D_FFP_DIFFUSE))
00128     {
00129         element = &si->elements[WINED3D_FFP_DIFFUSE];
00130         diffuse = element->data.addr;
00131 
00132         if (num_untracked_materials && element->format->id != WINED3DFMT_B8G8R8A8_UNORM)
00133             FIXME("Implement diffuse color tracking from %s\n", debug_d3dformat(element->format->id));
00134     }
00135     else
00136     {
00137         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
00138     }
00139 
00140     if (si->use_map & (1 << WINED3D_FFP_SPECULAR))
00141     {
00142         element = &si->elements[WINED3D_FFP_SPECULAR];
00143         specular = element->data.addr;
00144 
00145         /* special case where the fog density is stored in the specular alpha channel */
00146         if (state->render_states[WINED3D_RS_FOGENABLE]
00147                 && (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE
00148                     || si->elements[WINED3D_FFP_POSITION].format->id == WINED3DFMT_R32G32B32A32_FLOAT)
00149                 && state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
00150         {
00151             if (gl_info->supported[EXT_FOG_COORD])
00152             {
00153                 if (element->format->id == WINED3DFMT_B8G8R8A8_UNORM) specular_fog = TRUE;
00154                 else FIXME("Implement fog coordinates from %s\n", debug_d3dformat(element->format->id));
00155             }
00156             else
00157             {
00158                 static BOOL warned;
00159 
00160                 if (!warned)
00161                 {
00162                     /* TODO: Use the fog table code from old ddraw */
00163                     FIXME("Implement fog for transformed vertices in software\n");
00164                     warned = TRUE;
00165                 }
00166             }
00167         }
00168     }
00169     else if (gl_info->supported[EXT_SECONDARY_COLOR])
00170     {
00171         GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
00172     }
00173 
00174     for (textureNo = 0; textureNo < texture_stages; ++textureNo)
00175     {
00176         int coordIdx = state->texture_states[textureNo][WINED3D_TSS_TEXCOORD_INDEX];
00177         DWORD texture_idx = device->texUnitMap[textureNo];
00178 
00179         if (!gl_info->supported[ARB_MULTITEXTURE] && textureNo > 0)
00180         {
00181             FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
00182             continue;
00183         }
00184 
00185         if (!pixelShader && !state->textures[textureNo]) continue;
00186 
00187         if (texture_idx == WINED3D_UNMAPPED_STAGE) continue;
00188 
00189         if (coordIdx > 7)
00190         {
00191             TRACE("tex: %d - Skip tex coords, as being system generated\n", textureNo);
00192             continue;
00193         }
00194         else if (coordIdx < 0)
00195         {
00196             FIXME("tex: %d - Coord index %d is less than zero, expect a crash.\n", textureNo, coordIdx);
00197             continue;
00198         }
00199 
00200         if (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx)))
00201         {
00202             element = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
00203             texCoords[coordIdx] = element->data.addr;
00204             tex_mask |= (1 << textureNo);
00205         }
00206         else
00207         {
00208             TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
00209             if (gl_info->supported[ARB_MULTITEXTURE])
00210                 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
00211             else
00212                 glTexCoord4f(0, 0, 0, 1);
00213         }
00214     }
00215 
00216     /* We shouldn't start this function if any VBO is involved. Should I put a safety check here?
00217      * Guess it's not necessary(we crash then anyway) and would only eat CPU time
00218      */
00219 
00220     /* For each primitive */
00221     for (vx_index = 0; vx_index < NumVertexes; ++vx_index) {
00222         UINT texture, tmp_tex_mask;
00223         /* Blending data and Point sizes are not supported by this function. They are not supported by the fixed
00224          * function pipeline at all. A Fixme for them is printed after decoding the vertex declaration
00225          */
00226 
00227         /* For indexed data, we need to go a few more strides in */
00228         if (idxData)
00229         {
00230             /* Indexed so work out the number of strides to skip */
00231             if (idxSize == 2)
00232                 SkipnStrides = pIdxBufS[startIdx + vx_index] + state->base_vertex_index;
00233             else
00234                 SkipnStrides = pIdxBufL[startIdx + vx_index] + state->base_vertex_index;
00235         }
00236 
00237         tmp_tex_mask = tex_mask;
00238         for (texture = 0; tmp_tex_mask; tmp_tex_mask >>= 1, ++texture)
00239         {
00240             int coord_idx;
00241             const void *ptr;
00242             DWORD texture_idx;
00243 
00244             if (!(tmp_tex_mask & 1)) continue;
00245 
00246             coord_idx = state->texture_states[texture][WINED3D_TSS_TEXCOORD_INDEX];
00247             ptr = texCoords[coord_idx] + (SkipnStrides * si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].stride);
00248 
00249             texture_idx = device->texUnitMap[texture];
00250             multi_texcoord_funcs[si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format->emit_idx](
00251                     GL_TEXTURE0_ARB + texture_idx, ptr);
00252         }
00253 
00254         /* Diffuse -------------------------------- */
00255         if (diffuse) {
00256             const void *ptrToCoords = diffuse + SkipnStrides * si->elements[WINED3D_FFP_DIFFUSE].stride;
00257 
00258             diffuse_funcs[si->elements[WINED3D_FFP_DIFFUSE].format->emit_idx](ptrToCoords);
00259             if (num_untracked_materials)
00260             {
00261                 DWORD diffuseColor = ((const DWORD *)ptrToCoords)[0];
00262                 unsigned char i;
00263                 float color[4];
00264 
00265                 color[0] = D3DCOLOR_B_R(diffuseColor) / 255.0f;
00266                 color[1] = D3DCOLOR_B_G(diffuseColor) / 255.0f;
00267                 color[2] = D3DCOLOR_B_B(diffuseColor) / 255.0f;
00268                 color[3] = D3DCOLOR_B_A(diffuseColor) / 255.0f;
00269 
00270                 for (i = 0; i < num_untracked_materials; ++i)
00271                 {
00272                     glMaterialfv(GL_FRONT_AND_BACK, context->untracked_materials[i], color);
00273                 }
00274             }
00275         }
00276 
00277         /* Specular ------------------------------- */
00278         if (specular) {
00279             const void *ptrToCoords = specular + SkipnStrides * si->elements[WINED3D_FFP_SPECULAR].stride;
00280 
00281             specular_funcs[si->elements[WINED3D_FFP_SPECULAR].format->emit_idx](ptrToCoords);
00282 
00283             if (specular_fog)
00284             {
00285                 DWORD specularColor = *(const DWORD *)ptrToCoords;
00286                 GL_EXTCALL(glFogCoordfEXT((float) (specularColor >> 24)));
00287             }
00288         }
00289 
00290         /* Normal -------------------------------- */
00291         if (normal)
00292         {
00293             const void *ptrToCoords = normal + SkipnStrides * si->elements[WINED3D_FFP_NORMAL].stride;
00294             normal_funcs[si->elements[WINED3D_FFP_NORMAL].format->emit_idx](ptrToCoords);
00295         }
00296 
00297         /* Position -------------------------------- */
00298         if (position) {
00299             const void *ptrToCoords = position + SkipnStrides * si->elements[WINED3D_FFP_POSITION].stride;
00300             position_funcs[si->elements[WINED3D_FFP_POSITION].format->emit_idx](ptrToCoords);
00301         }
00302 
00303         /* For non indexed mode, step onto next parts */
00304         if (!idxData) ++SkipnStrides;
00305     }
00306 
00307     glEnd();
00308     checkGLcall("glEnd and previous calls");
00309 }
00310 
00311 /* GL locking is done by the caller */
00312 static inline void send_attribute(const struct wined3d_gl_info *gl_info,
00313         enum wined3d_format_id format, const UINT index, const void *ptr)
00314 {
00315     switch(format)
00316     {
00317         case WINED3DFMT_R32_FLOAT:
00318             GL_EXTCALL(glVertexAttrib1fvARB(index, ptr));
00319             break;
00320         case WINED3DFMT_R32G32_FLOAT:
00321             GL_EXTCALL(glVertexAttrib2fvARB(index, ptr));
00322             break;
00323         case WINED3DFMT_R32G32B32_FLOAT:
00324             GL_EXTCALL(glVertexAttrib3fvARB(index, ptr));
00325             break;
00326         case WINED3DFMT_R32G32B32A32_FLOAT:
00327             GL_EXTCALL(glVertexAttrib4fvARB(index, ptr));
00328             break;
00329 
00330         case WINED3DFMT_R8G8B8A8_UINT:
00331             GL_EXTCALL(glVertexAttrib4ubvARB(index, ptr));
00332             break;
00333         case WINED3DFMT_B8G8R8A8_UNORM:
00334             if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
00335             {
00336                 const DWORD *src = ptr;
00337                 DWORD c = *src & 0xff00ff00;
00338                 c |= (*src & 0xff0000) >> 16;
00339                 c |= (*src & 0xff) << 16;
00340                 GL_EXTCALL(glVertexAttrib4NubvARB(index, (GLubyte *)&c));
00341                 break;
00342             }
00343             /* else fallthrough */
00344         case WINED3DFMT_R8G8B8A8_UNORM:
00345             GL_EXTCALL(glVertexAttrib4NubvARB(index, ptr));
00346             break;
00347 
00348         case WINED3DFMT_R16G16_SINT:
00349             GL_EXTCALL(glVertexAttrib4svARB(index, ptr));
00350             break;
00351         case WINED3DFMT_R16G16B16A16_SINT:
00352             GL_EXTCALL(glVertexAttrib4svARB(index, ptr));
00353             break;
00354 
00355         case WINED3DFMT_R16G16_SNORM:
00356         {
00357             GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
00358             GL_EXTCALL(glVertexAttrib4NsvARB(index, s));
00359             break;
00360         }
00361         case WINED3DFMT_R16G16_UNORM:
00362         {
00363             GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
00364             GL_EXTCALL(glVertexAttrib4NusvARB(index, s));
00365             break;
00366         }
00367         case WINED3DFMT_R16G16B16A16_SNORM:
00368             GL_EXTCALL(glVertexAttrib4NsvARB(index, ptr));
00369             break;
00370         case WINED3DFMT_R16G16B16A16_UNORM:
00371             GL_EXTCALL(glVertexAttrib4NusvARB(index, ptr));
00372             break;
00373 
00374         case WINED3DFMT_R10G10B10A2_UINT:
00375             FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
00376             /*glVertexAttrib3usvARB(instancedData[j], (GLushort *) ptr); Does not exist */
00377             break;
00378         case WINED3DFMT_R10G10B10A2_SNORM:
00379             FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
00380             /*glVertexAttrib3NusvARB(instancedData[j], (GLushort *) ptr); Does not exist */
00381             break;
00382 
00383         case WINED3DFMT_R16G16_FLOAT:
00384             /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
00385              * byte float according to the IEEE standard
00386              */
00387             if (gl_info->supported[NV_HALF_FLOAT] && gl_info->supported[NV_VERTEX_PROGRAM])
00388             {
00389                 /* Not supported by GL_ARB_half_float_vertex */
00390                 GL_EXTCALL(glVertexAttrib2hvNV(index, ptr));
00391             }
00392             else
00393             {
00394                 float x = float_16_to_32(((const unsigned short *)ptr) + 0);
00395                 float y = float_16_to_32(((const unsigned short *)ptr) + 1);
00396                 GL_EXTCALL(glVertexAttrib2fARB(index, x, y));
00397             }
00398             break;
00399         case WINED3DFMT_R16G16B16A16_FLOAT:
00400             if (gl_info->supported[NV_HALF_FLOAT] && gl_info->supported[NV_VERTEX_PROGRAM])
00401             {
00402                 /* Not supported by GL_ARB_half_float_vertex */
00403                 GL_EXTCALL(glVertexAttrib4hvNV(index, ptr));
00404             }
00405             else
00406             {
00407                 float x = float_16_to_32(((const unsigned short *)ptr) + 0);
00408                 float y = float_16_to_32(((const unsigned short *)ptr) + 1);
00409                 float z = float_16_to_32(((const unsigned short *)ptr) + 2);
00410                 float w = float_16_to_32(((const unsigned short *)ptr) + 3);
00411                 GL_EXTCALL(glVertexAttrib4fARB(index, x, y, z, w));
00412             }
00413             break;
00414 
00415         default:
00416             ERR("Unexpected attribute format: %s\n", debug_d3dformat(format));
00417             break;
00418     }
00419 }
00420 
00421 /* GL locking is done by the caller */
00422 static void drawStridedSlowVs(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state,
00423         const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType,
00424         const void *idxData, UINT idxSize, UINT startIdx)
00425 {
00426     LONG SkipnStrides = startIdx + state->load_base_vertex_index;
00427     const DWORD *pIdxBufL = NULL;
00428     const WORD *pIdxBufS = NULL;
00429     UINT vx_index;
00430     int i;
00431     const BYTE *ptr;
00432 
00433     if (idxSize)
00434     {
00435         /* Immediate mode drawing can't make use of indices in a vbo - get the
00436          * data from the index buffer. If the index buffer has no vbo (not
00437          * supported or other reason), or with user pointer drawing idxData
00438          * will be non-NULL. */
00439         if (!idxData)
00440             idxData = buffer_get_sysmem(state->index_buffer, gl_info);
00441 
00442         if (idxSize == 2) pIdxBufS = idxData;
00443         else pIdxBufL = idxData;
00444     } else if (idxData) {
00445         ERR("non-NULL idxData with 0 idxSize, this should never happen\n");
00446         return;
00447     }
00448 
00449     /* Start drawing in GL */
00450     glBegin(glPrimitiveType);
00451 
00452     for (vx_index = 0; vx_index < numberOfVertices; ++vx_index)
00453     {
00454         if (idxData)
00455         {
00456             /* Indexed so work out the number of strides to skip */
00457             if (idxSize == 2)
00458                 SkipnStrides = pIdxBufS[startIdx + vx_index] + state->load_base_vertex_index;
00459             else
00460                 SkipnStrides = pIdxBufL[startIdx + vx_index] + state->load_base_vertex_index;
00461         }
00462 
00463         for (i = MAX_ATTRIBS - 1; i >= 0; i--)
00464         {
00465             if (!(si->use_map & (1 << i))) continue;
00466 
00467             ptr = si->elements[i].data.addr + si->elements[i].stride * SkipnStrides;
00468 
00469             send_attribute(gl_info, si->elements[i].format->id, i, ptr);
00470         }
00471         SkipnStrides++;
00472     }
00473 
00474     glEnd();
00475 }
00476 
00477 /* GL locking is done by the caller */
00478 static void drawStridedInstanced(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state,
00479         const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType,
00480         const void *idxData, UINT idxSize, UINT startIdx, UINT base_vertex_index)
00481 {
00482     UINT numInstances = 0, i;
00483     int numInstancedAttribs = 0, j;
00484     UINT instancedData[sizeof(si->elements) / sizeof(*si->elements) /* 16 */];
00485     GLenum idxtype = idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
00486 
00487     if (!idxSize)
00488     {
00489         /* This is a nasty thing. MSDN says no hardware supports that and apps have to use software vertex processing.
00490          * We don't support this for now
00491          *
00492          * Shouldn't be too hard to support with opengl, in theory just call glDrawArrays instead of drawElements.
00493          * But the StreamSourceFreq value has a different meaning in that situation.
00494          */
00495         FIXME("Non-indexed instanced drawing is not supported\n");
00496         return;
00497     }
00498 
00499     /* First, figure out how many instances we have to draw */
00500     for (i = 0; i < MAX_STREAMS; ++i)
00501     {
00502         /* Look at the streams and take the first one which matches */
00503         if (state->streams[i].buffer
00504                 && ((state->streams[i].flags & WINED3DSTREAMSOURCE_INSTANCEDATA)
00505                 || (state->streams[i].flags & WINED3DSTREAMSOURCE_INDEXEDDATA)))
00506         {
00507             /* Use the specified number of instances from the first matched
00508              * stream. A streamFreq of 0 (with INSTANCEDATA or INDEXEDDATA)
00509              * is handled as 1. See d3d9/tests/visual.c-> stream_test(). */
00510             numInstances = state->streams[i].frequency ? state->streams[i].frequency : 1;
00511             break;
00512         }
00513     }
00514 
00515     for (i = 0; i < sizeof(si->elements) / sizeof(*si->elements); ++i)
00516     {
00517         if (!(si->use_map & (1 << i))) continue;
00518 
00519         if (state->streams[si->elements[i].stream_idx].flags & WINED3DSTREAMSOURCE_INSTANCEDATA)
00520         {
00521             instancedData[numInstancedAttribs] = i;
00522             numInstancedAttribs++;
00523         }
00524     }
00525 
00526     /* now draw numInstances instances :-) */
00527     for(i = 0; i < numInstances; i++) {
00528         /* Specify the instanced attributes using immediate mode calls */
00529         for(j = 0; j < numInstancedAttribs; j++) {
00530             const BYTE *ptr = si->elements[instancedData[j]].data.addr
00531                     + si->elements[instancedData[j]].stride * i;
00532             if (si->elements[instancedData[j]].data.buffer_object)
00533             {
00534                 struct wined3d_buffer *vb = state->streams[si->elements[instancedData[j]].stream_idx].buffer;
00535                 ptr += (ULONG_PTR)buffer_get_sysmem(vb, gl_info);
00536             }
00537 
00538             send_attribute(gl_info, si->elements[instancedData[j]].format->id, instancedData[j], ptr);
00539         }
00540 
00541         if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
00542         {
00543             GL_EXTCALL(glDrawElementsBaseVertex(glPrimitiveType, numberOfVertices, idxtype,
00544                         (const char *)idxData+(idxSize * startIdx), base_vertex_index));
00545             checkGLcall("glDrawElementsBaseVertex");
00546         }
00547         else
00548         {
00549             glDrawElements(glPrimitiveType, numberOfVertices, idxtype,
00550                         (const char *)idxData+(idxSize * startIdx));
00551             checkGLcall("glDrawElements");
00552         }
00553     }
00554 }
00555 
00556 static void remove_vbos(const struct wined3d_gl_info *gl_info,
00557         const struct wined3d_state *state, struct wined3d_stream_info *s)
00558 {
00559     unsigned int i;
00560 
00561     for (i = 0; i < (sizeof(s->elements) / sizeof(*s->elements)); ++i)
00562     {
00563         struct wined3d_stream_info_element *e;
00564 
00565         if (!(s->use_map & (1 << i))) continue;
00566 
00567         e = &s->elements[i];
00568         if (e->data.buffer_object)
00569         {
00570             struct wined3d_buffer *vb = state->streams[e->stream_idx].buffer;
00571             e->data.buffer_object = 0;
00572             e->data.addr = (BYTE *)((ULONG_PTR)e->data.addr + (ULONG_PTR)buffer_get_sysmem(vb, gl_info));
00573         }
00574     }
00575 }
00576 
00577 /* Routine common to the draw primitive and draw indexed primitive routines */
00578 void drawPrimitive(struct wined3d_device *device, UINT index_count, UINT StartIdx, UINT idxSize, const void *idxData)
00579 {
00580     const struct wined3d_state *state = &device->stateBlock->state;
00581     struct wined3d_context *context;
00582     unsigned int i;
00583 
00584     if (!index_count) return;
00585 
00586     if (state->render_states[WINED3D_RS_COLORWRITEENABLE])
00587     {
00588         /* Invalidate the back buffer memory so LockRect will read it the next time */
00589         for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
00590         {
00591             struct wined3d_surface *target = device->fb.render_targets[i];
00592             if (target)
00593             {
00594                 surface_load_location(target, target->draw_binding, NULL);
00595                 surface_modify_location(target, target->draw_binding, TRUE);
00596             }
00597         }
00598     }
00599 
00600     /* Signals other modules that a drawing is in progress and the stateblock finalized */
00601     device->isInDraw = TRUE;
00602 
00603     context = context_acquire(device, device->fb.render_targets[0]);
00604     if (!context->valid)
00605     {
00606         context_release(context);
00607         WARN("Invalid context, skipping draw.\n");
00608         return;
00609     }
00610 
00611     if (device->fb.depth_stencil)
00612     {
00613         /* Note that this depends on the context_acquire() call above to set
00614          * context->render_offscreen properly. We don't currently take the
00615          * Z-compare function into account, but we could skip loading the
00616          * depthstencil for D3DCMP_NEVER and D3DCMP_ALWAYS as well. Also note
00617          * that we never copy the stencil data.*/
00618         DWORD location = context->render_offscreen ? device->fb.depth_stencil->draw_binding : SFLAG_INDRAWABLE;
00619         if (state->render_states[WINED3D_RS_ZWRITEENABLE] || state->render_states[WINED3D_RS_ZENABLE])
00620         {
00621             struct wined3d_surface *ds = device->fb.depth_stencil;
00622             RECT current_rect, draw_rect, r;
00623 
00624             if (!context->render_offscreen && ds != device->onscreen_depth_stencil)
00625                 device_switch_onscreen_ds(device, context, ds);
00626 
00627             if (ds->flags & location)
00628                 SetRect(&current_rect, 0, 0, ds->ds_current_size.cx, ds->ds_current_size.cy);
00629             else
00630                 SetRectEmpty(&current_rect);
00631 
00632             wined3d_get_draw_rect(state, &draw_rect);
00633 
00634             IntersectRect(&r, &draw_rect, &current_rect);
00635             if (!EqualRect(&r, &draw_rect))
00636                 surface_load_ds_location(ds, context, location);
00637         }
00638     }
00639 
00640     if (!context_apply_draw_state(context, device))
00641     {
00642         context_release(context);
00643         WARN("Unable to apply draw state, skipping draw.\n");
00644         return;
00645     }
00646 
00647     if (device->fb.depth_stencil && state->render_states[WINED3D_RS_ZWRITEENABLE])
00648     {
00649         struct wined3d_surface *ds = device->fb.depth_stencil;
00650         DWORD location = context->render_offscreen ? ds->draw_binding : SFLAG_INDRAWABLE;
00651 
00652         surface_modify_ds_location(ds, location, ds->ds_current_size.cx, ds->ds_current_size.cy);
00653     }
00654 
00655     if ((!context->gl_info->supported[WINED3D_GL_VERSION_2_0]
00656             || (!glPointParameteri && !context->gl_info->supported[NV_POINT_SPRITE]))
00657             && context->render_offscreen
00658             && state->render_states[WINED3D_RS_POINTSPRITEENABLE]
00659             && state->gl_primitive_type == GL_POINTS)
00660     {
00661         FIXME("Point sprite coordinate origin switching not supported.\n");
00662     }
00663 
00664     /* Ok, we will be updating the screen from here onwards so grab the lock */
00665     ENTER_GL();
00666     {
00667         GLenum glPrimType = state->gl_primitive_type;
00668         INT base_vertex_index = state->base_vertex_index;
00669         BOOL emulation = FALSE;
00670         const struct wined3d_stream_info *stream_info = &device->strided_streams;
00671         struct wined3d_stream_info stridedlcl;
00672 
00673         if (!use_vs(state))
00674         {
00675             if (!stream_info->position_transformed && context->num_untracked_materials
00676                     && state->render_states[WINED3D_RS_LIGHTING])
00677             {
00678                 static BOOL warned;
00679                 if (!warned) {
00680                     FIXME("Using software emulation because not all material properties could be tracked\n");
00681                     warned = TRUE;
00682                 } else {
00683                     TRACE("Using software emulation because not all material properties could be tracked\n");
00684                 }
00685                 emulation = TRUE;
00686             }
00687             else if (context->fog_coord && state->render_states[WINED3D_RS_FOGENABLE])
00688             {
00689                 /* Either write a pipeline replacement shader or convert the specular alpha from unsigned byte
00690                  * to a float in the vertex buffer
00691                  */
00692                 static BOOL warned;
00693                 if (!warned) {
00694                     FIXME("Using software emulation because manual fog coordinates are provided\n");
00695                     warned = TRUE;
00696                 } else {
00697                     TRACE("Using software emulation because manual fog coordinates are provided\n");
00698                 }
00699                 emulation = TRUE;
00700             }
00701 
00702             if(emulation) {
00703                 stream_info = &stridedlcl;
00704                 memcpy(&stridedlcl, &device->strided_streams, sizeof(stridedlcl));
00705                 remove_vbos(context->gl_info, state, &stridedlcl);
00706             }
00707         }
00708 
00709         if (device->useDrawStridedSlow || emulation)
00710         {
00711             /* Immediate mode drawing */
00712             if (use_vs(state))
00713             {
00714                 static BOOL warned;
00715                 if (!warned) {
00716                     FIXME("Using immediate mode with vertex shaders for half float emulation\n");
00717                     warned = TRUE;
00718                 } else {
00719                     TRACE("Using immediate mode with vertex shaders for half float emulation\n");
00720                 }
00721                 drawStridedSlowVs(context->gl_info, state, stream_info,
00722                         index_count, glPrimType, idxData, idxSize, StartIdx);
00723             }
00724             else
00725             {
00726                 drawStridedSlow(device, context, stream_info, index_count,
00727                         glPrimType, idxData, idxSize, StartIdx);
00728             }
00729         }
00730         else if (device->instancedDraw)
00731         {
00732             /* Instancing emulation with mixing immediate mode and arrays */
00733             drawStridedInstanced(context->gl_info, state, stream_info,
00734                     index_count, glPrimType, idxData, idxSize, StartIdx, base_vertex_index);
00735         }
00736         else
00737         {
00738             drawStridedFast(context->gl_info, glPrimType, index_count, idxSize, idxData, StartIdx, base_vertex_index);
00739         }
00740     }
00741 
00742     /* Finished updating the screen, restore lock */
00743     LEAVE_GL();
00744 
00745     for(i = 0; i < device->num_buffer_queries; ++i)
00746     {
00747         wined3d_event_query_issue(device->buffer_queries[i], device);
00748     }
00749 
00750     if (wined3d_settings.strict_draw_ordering) wglFlush(); /* Flush to ensure ordering across contexts. */
00751 
00752     context_release(context);
00753 
00754     TRACE("Done all gl drawing\n");
00755 
00756     /* Control goes back to the device, stateblock values may change again */
00757     device->isInDraw = FALSE;
00758 }
00759 
00760 static void normalize_normal(float *n) {
00761     float length = n[0] * n[0] + n[1] * n[1] + n[2] * n[2];
00762     if (length == 0.0f) return;
00763     length = sqrtf(length);
00764     n[0] = n[0] / length;
00765     n[1] = n[1] / length;
00766     n[2] = n[2] / length;
00767 }
00768 
00769 /* Tesselates a high order rectangular patch into single triangles using gl evaluators
00770  *
00771  * The problem is that OpenGL does not offer a direct way to return the tesselated primitives,
00772  * and they can't be sent off for rendering directly either. Tesselating is slow, so we want
00773  * to cache the patches in a vertex buffer. But more importantly, gl can't bind generated
00774  * attributes to numbered shader attributes, so we have to store them and rebind them as needed
00775  * in drawprim.
00776  *
00777  * To read back, the opengl feedback mode is used. This creates a problem because we want
00778  * untransformed, unlit vertices, but feedback runs everything through transform and lighting.
00779  * Thus disable lighting and set identity matrices to get unmodified colors and positions.
00780  * To overcome clipping find the biggest x, y and z values of the vertices in the patch and scale
00781  * them to [-1.0;+1.0] and set the viewport up to scale them back.
00782  *
00783  * Normals are more tricky: Draw white vertices with 3 directional lights, and calculate the
00784  * resulting colors back to the normals.
00785  *
00786  * NOTE: This function activates a context for blitting, modifies matrices & viewport, but
00787  * does not restore it because normally a draw follows immediately afterwards. The caller is
00788  * responsible of taking care that either the gl states are restored, or the context activated
00789  * for drawing to reset the lastWasBlit flag.
00790  */
00791 HRESULT tesselate_rectpatch(struct wined3d_device *This, struct WineD3DRectPatch *patch)
00792 {
00793     unsigned int i, j, num_quads, out_vertex_size, buffer_size, d3d_out_vertex_size;
00794     const struct wined3d_rect_patch_info *info = &patch->rect_patch_info;
00795     float max_x = 0.0f, max_y = 0.0f, max_z = 0.0f, neg_z = 0.0f;
00796     struct wined3d_state *state = &This->stateBlock->state;
00797     struct wined3d_stream_info stream_info;
00798     struct wined3d_stream_info_element *e;
00799     struct wined3d_context *context;
00800     struct wined3d_shader *vs;
00801     const BYTE *data;
00802     DWORD vtxStride;
00803     GLenum feedback_type;
00804     GLfloat *feedbuffer;
00805 
00806     /* Simply activate the context for blitting. This disables all the things we don't want and
00807      * takes care of dirtifying. Dirtifying is preferred over pushing / popping, since drawing the
00808      * patch (as opposed to normal draws) will most likely need different changes anyway. */
00809     context = context_acquire(This, NULL);
00810     context_apply_blit_state(context, This);
00811 
00812     /* First, locate the position data. This is provided in a vertex buffer in
00813      * the stateblock. Beware of VBOs. */
00814     vs = state->vertex_shader;
00815     state->vertex_shader = NULL;
00816     device_stream_info_from_declaration(This, &stream_info, NULL);
00817     state->vertex_shader = vs;
00818 
00819     e = &stream_info.elements[WINED3D_FFP_POSITION];
00820     if (e->data.buffer_object)
00821     {
00822         struct wined3d_buffer *vb = state->streams[e->stream_idx].buffer;
00823         e->data.addr = (BYTE *)((ULONG_PTR)e->data.addr + (ULONG_PTR)buffer_get_sysmem(vb, context->gl_info));
00824     }
00825     vtxStride = e->stride;
00826     data = e->data.addr
00827             + vtxStride * info->stride * info->start_vertex_offset_height
00828             + vtxStride * info->start_vertex_offset_width;
00829 
00830     /* Not entirely sure about what happens with transformed vertices */
00831     if (stream_info.position_transformed) FIXME("Transformed position in rectpatch generation\n");
00832 
00833     if(vtxStride % sizeof(GLfloat)) {
00834         /* glMap2f reads vertex sizes in GLfloats, the d3d stride is in bytes.
00835          * I don't see how the stride could not be a multiple of 4, but make sure
00836          * to check it
00837          */
00838         ERR("Vertex stride is not a multiple of sizeof(GLfloat)\n");
00839     }
00840     if (info->basis != WINED3D_BASIS_BEZIER)
00841         FIXME("Basis is %s, how to handle this?\n", debug_d3dbasis(info->basis));
00842     if (info->degree != WINED3D_DEGREE_CUBIC)
00843         FIXME("Degree is %s, how to handle this?\n", debug_d3ddegree(info->degree));
00844 
00845     /* First, get the boundary cube of the input data */
00846     for (j = 0; j < info->height; ++j)
00847     {
00848         for (i = 0; i < info->width; ++i)
00849         {
00850             const float *v = (const float *)(data + vtxStride * i + vtxStride * info->stride * j);
00851             if(fabs(v[0]) > max_x) max_x = fabsf(v[0]);
00852             if(fabs(v[1]) > max_y) max_y = fabsf(v[1]);
00853             if(fabs(v[2]) > max_z) max_z = fabsf(v[2]);
00854             if(v[2] < neg_z) neg_z = v[2];
00855         }
00856     }
00857 
00858     /* This needs some improvements in the vertex decl code */
00859     FIXME("Cannot find data to generate. Only generating position and normals\n");
00860     patch->has_normals = TRUE;
00861     patch->has_texcoords = FALSE;
00862 
00863     ENTER_GL();
00864 
00865     glMatrixMode(GL_PROJECTION);
00866     checkGLcall("glMatrixMode(GL_PROJECTION)");
00867     glLoadIdentity();
00868     checkGLcall("glLoadIdentity()");
00869     glScalef(1.0f / (max_x), 1.0f / (max_y), max_z == 0.0f ? 1.0f : 1.0f / (2.0f * max_z));
00870     glTranslatef(0.0f, 0.0f, 0.5f);
00871     checkGLcall("glScalef");
00872     glViewport(-max_x, -max_y, 2 * (max_x), 2 * (max_y));
00873     checkGLcall("glViewport");
00874 
00875     /* Some states to take care of. If we're in wireframe opengl will produce lines, and confuse
00876      * our feedback buffer parser
00877      */
00878     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00879     checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
00880     context_invalidate_state(context, STATE_RENDER(WINED3D_RS_FILLMODE));
00881     if (patch->has_normals)
00882     {
00883         static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
00884         static const GLfloat red[]   = {1.0f, 0.0f, 0.0f, 0.0f};
00885         static const GLfloat green[] = {0.0f, 1.0f, 0.0f, 0.0f};
00886         static const GLfloat blue[]  = {0.0f, 0.0f, 1.0f, 0.0f};
00887         static const GLfloat white[] = {1.0f, 1.0f, 1.0f, 1.0f};
00888         glEnable(GL_LIGHTING);
00889         checkGLcall("glEnable(GL_LIGHTING)");
00890         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, black);
00891         checkGLcall("glLightModel for MODEL_AMBIENT");
00892         context_invalidate_state(context, STATE_RENDER(WINED3D_RS_AMBIENT));
00893 
00894         for (i = 3; i < context->gl_info->limits.lights; ++i)
00895         {
00896             glDisable(GL_LIGHT0 + i);
00897             checkGLcall("glDisable(GL_LIGHT0 + i)");
00898             context_invalidate_state(context, STATE_ACTIVELIGHT(i));
00899         }
00900 
00901         context_invalidate_state(context, STATE_ACTIVELIGHT(0));
00902         glLightfv(GL_LIGHT0, GL_DIFFUSE, red);
00903         glLightfv(GL_LIGHT0, GL_SPECULAR, black);
00904         glLightfv(GL_LIGHT0, GL_AMBIENT, black);
00905         glLightfv(GL_LIGHT0, GL_POSITION, red);
00906         glEnable(GL_LIGHT0);
00907         checkGLcall("Setting up light 1");
00908         context_invalidate_state(context, STATE_ACTIVELIGHT(1));
00909         glLightfv(GL_LIGHT1, GL_DIFFUSE, green);
00910         glLightfv(GL_LIGHT1, GL_SPECULAR, black);
00911         glLightfv(GL_LIGHT1, GL_AMBIENT, black);
00912         glLightfv(GL_LIGHT1, GL_POSITION, green);
00913         glEnable(GL_LIGHT1);
00914         checkGLcall("Setting up light 2");
00915         context_invalidate_state(context, STATE_ACTIVELIGHT(2));
00916         glLightfv(GL_LIGHT2, GL_DIFFUSE, blue);
00917         glLightfv(GL_LIGHT2, GL_SPECULAR, black);
00918         glLightfv(GL_LIGHT2, GL_AMBIENT, black);
00919         glLightfv(GL_LIGHT2, GL_POSITION, blue);
00920         glEnable(GL_LIGHT2);
00921         checkGLcall("Setting up light 3");
00922 
00923         context_invalidate_state(context, STATE_MATERIAL);
00924         context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORVERTEX));
00925         glDisable(GL_COLOR_MATERIAL);
00926         glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
00927         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
00928         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, white);
00929         checkGLcall("Setting up materials");
00930     }
00931 
00932     /* Enable the needed maps.
00933      * GL_MAP2_VERTEX_3 is needed for positional data.
00934      * GL_AUTO_NORMAL to generate normals from the position. Do not use GL_MAP2_NORMAL.
00935      * GL_MAP2_TEXTURE_COORD_4 for texture coords
00936      */
00937     num_quads = ceilf(patch->numSegs[0]) * ceilf(patch->numSegs[1]);
00938     out_vertex_size = 3 /* position */;
00939     d3d_out_vertex_size = 3;
00940     glEnable(GL_MAP2_VERTEX_3);
00941     if(patch->has_normals && patch->has_texcoords) {
00942         FIXME("Texcoords not handled yet\n");
00943         feedback_type = GL_3D_COLOR_TEXTURE;
00944         out_vertex_size += 8;
00945         d3d_out_vertex_size += 7;
00946         glEnable(GL_AUTO_NORMAL);
00947         glEnable(GL_MAP2_TEXTURE_COORD_4);
00948     } else if(patch->has_texcoords) {
00949         FIXME("Texcoords not handled yet\n");
00950         feedback_type = GL_3D_COLOR_TEXTURE;
00951         out_vertex_size += 7;
00952         d3d_out_vertex_size += 4;
00953         glEnable(GL_MAP2_TEXTURE_COORD_4);
00954     } else if(patch->has_normals) {
00955         feedback_type = GL_3D_COLOR;
00956         out_vertex_size += 4;
00957         d3d_out_vertex_size += 3;
00958         glEnable(GL_AUTO_NORMAL);
00959     } else {
00960         feedback_type = GL_3D;
00961     }
00962     checkGLcall("glEnable vertex attrib generation");
00963 
00964     buffer_size = num_quads * out_vertex_size * 2 /* triangle list */ * 3 /* verts per tri */
00965                    + 4 * num_quads /* 2 triangle markers per quad + num verts in tri */;
00966     feedbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_size * sizeof(float) * 8);
00967 
00968     glMap2f(GL_MAP2_VERTEX_3,
00969             0.0f, 1.0f, vtxStride / sizeof(float), info->width,
00970             0.0f, 1.0f, info->stride * vtxStride / sizeof(float), info->height,
00971             (const GLfloat *)data);
00972     checkGLcall("glMap2f");
00973     if (patch->has_texcoords)
00974     {
00975         glMap2f(GL_MAP2_TEXTURE_COORD_4,
00976                 0.0f, 1.0f, vtxStride / sizeof(float), info->width,
00977                 0.0f, 1.0f, info->stride * vtxStride / sizeof(float), info->height,
00978                 (const GLfloat *)data);
00979         checkGLcall("glMap2f");
00980     }
00981     glMapGrid2f(ceilf(patch->numSegs[0]), 0.0f, 1.0f, ceilf(patch->numSegs[1]), 0.0f, 1.0f);
00982     checkGLcall("glMapGrid2f");
00983 
00984     glFeedbackBuffer(buffer_size * 2, feedback_type, feedbuffer);
00985     checkGLcall("glFeedbackBuffer");
00986     glRenderMode(GL_FEEDBACK);
00987 
00988     glEvalMesh2(GL_FILL, 0, ceilf(patch->numSegs[0]), 0, ceilf(patch->numSegs[1]));
00989     checkGLcall("glEvalMesh2");
00990 
00991     i = glRenderMode(GL_RENDER);
00992     if(i == -1) {
00993         LEAVE_GL();
00994         ERR("Feedback failed. Expected %d elements back\n", buffer_size);
00995         HeapFree(GetProcessHeap(), 0, feedbuffer);
00996         context_release(context);
00997         return WINED3DERR_DRIVERINTERNALERROR;
00998     } else if(i != buffer_size) {
00999         LEAVE_GL();
01000         ERR("Unexpected amount of elements returned. Expected %d, got %d\n", buffer_size, i);
01001         HeapFree(GetProcessHeap(), 0, feedbuffer);
01002         context_release(context);
01003         return WINED3DERR_DRIVERINTERNALERROR;
01004     } else {
01005         TRACE("Got %d elements as expected\n", i);
01006     }
01007 
01008     HeapFree(GetProcessHeap(), 0, patch->mem);
01009     patch->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_quads * 6 * d3d_out_vertex_size * sizeof(float) * 8);
01010     i = 0;
01011     for(j = 0; j < buffer_size; j += (3 /* num verts */ * out_vertex_size + 2 /* tri marker */)) {
01012         if(feedbuffer[j] != GL_POLYGON_TOKEN) {
01013             ERR("Unexpected token: %f\n", feedbuffer[j]);
01014             continue;
01015         }
01016         if(feedbuffer[j + 1] != 3) {
01017             ERR("Unexpected polygon: %f corners\n", feedbuffer[j + 1]);
01018             continue;
01019         }
01020         /* Somehow there are different ideas about back / front facing, so fix up the
01021          * vertex order
01022          */
01023         patch->mem[i + 0] =  feedbuffer[j + out_vertex_size * 2 + 2]; /* x, triangle 2 */
01024         patch->mem[i + 1] =  feedbuffer[j + out_vertex_size * 2 + 3]; /* y, triangle 2 */
01025         patch->mem[i + 2] = (feedbuffer[j + out_vertex_size * 2 + 4] - 0.5f) * 4.0f * max_z; /* z, triangle 3 */
01026         if(patch->has_normals) {
01027             patch->mem[i + 3] = feedbuffer[j + out_vertex_size * 2 + 5];
01028             patch->mem[i + 4] = feedbuffer[j + out_vertex_size * 2 + 6];
01029             patch->mem[i + 5] = feedbuffer[j + out_vertex_size * 2 + 7];
01030         }
01031         i += d3d_out_vertex_size;
01032 
01033         patch->mem[i + 0] =  feedbuffer[j + out_vertex_size * 1 + 2]; /* x, triangle 2 */
01034         patch->mem[i + 1] =  feedbuffer[j + out_vertex_size * 1 + 3]; /* y, triangle 2 */
01035         patch->mem[i + 2] = (feedbuffer[j + out_vertex_size * 1 + 4] - 0.5f) * 4.0f * max_z; /* z, triangle 2 */
01036         if(patch->has_normals) {
01037             patch->mem[i + 3] = feedbuffer[j + out_vertex_size * 1 + 5];
01038             patch->mem[i + 4] = feedbuffer[j + out_vertex_size * 1 + 6];
01039             patch->mem[i + 5] = feedbuffer[j + out_vertex_size * 1 + 7];
01040         }
01041         i += d3d_out_vertex_size;
01042 
01043         patch->mem[i + 0] =  feedbuffer[j + out_vertex_size * 0 + 2]; /* x, triangle 1 */
01044         patch->mem[i + 1] =  feedbuffer[j + out_vertex_size * 0 + 3]; /* y, triangle 1 */
01045         patch->mem[i + 2] = (feedbuffer[j + out_vertex_size * 0 + 4] - 0.5f) * 4.0f * max_z; /* z, triangle 1 */
01046         if(patch->has_normals) {
01047             patch->mem[i + 3] = feedbuffer[j + out_vertex_size * 0 + 5];
01048             patch->mem[i + 4] = feedbuffer[j + out_vertex_size * 0 + 6];
01049             patch->mem[i + 5] = feedbuffer[j + out_vertex_size * 0 + 7];
01050         }
01051         i += d3d_out_vertex_size;
01052     }
01053 
01054     if(patch->has_normals) {
01055         /* Now do the same with reverse light directions */
01056         static const GLfloat x[] = {-1.0f,  0.0f,  0.0f, 0.0f};
01057         static const GLfloat y[] = { 0.0f, -1.0f,  0.0f, 0.0f};
01058         static const GLfloat z[] = { 0.0f,  0.0f, -1.0f, 0.0f};
01059         glLightfv(GL_LIGHT0, GL_POSITION, x);
01060         glLightfv(GL_LIGHT1, GL_POSITION, y);
01061         glLightfv(GL_LIGHT2, GL_POSITION, z);
01062         checkGLcall("Setting up reverse light directions");
01063 
01064         glRenderMode(GL_FEEDBACK);
01065         checkGLcall("glRenderMode(GL_FEEDBACK)");
01066         glEvalMesh2(GL_FILL, 0, ceilf(patch->numSegs[0]), 0, ceilf(patch->numSegs[1]));
01067         checkGLcall("glEvalMesh2");
01068         i = glRenderMode(GL_RENDER);
01069         checkGLcall("glRenderMode(GL_RENDER)");
01070 
01071         i = 0;
01072         for(j = 0; j < buffer_size; j += (3 /* num verts */ * out_vertex_size + 2 /* tri marker */)) {
01073             if(feedbuffer[j] != GL_POLYGON_TOKEN) {
01074                 ERR("Unexpected token: %f\n", feedbuffer[j]);
01075                 continue;
01076             }
01077             if(feedbuffer[j + 1] != 3) {
01078                 ERR("Unexpected polygon: %f corners\n", feedbuffer[j + 1]);
01079                 continue;
01080             }
01081             if(patch->mem[i + 3] == 0.0f)
01082                 patch->mem[i + 3] = -feedbuffer[j + out_vertex_size * 2 + 5];
01083             if(patch->mem[i + 4] == 0.0f)
01084                 patch->mem[i + 4] = -feedbuffer[j + out_vertex_size * 2 + 6];
01085             if(patch->mem[i + 5] == 0.0f)
01086                 patch->mem[i + 5] = -feedbuffer[j + out_vertex_size * 2 + 7];
01087             normalize_normal(patch->mem + i + 3);
01088             i += d3d_out_vertex_size;
01089 
01090             if(patch->mem[i + 3] == 0.0f)
01091                 patch->mem[i + 3] = -feedbuffer[j + out_vertex_size * 1 + 5];
01092             if(patch->mem[i + 4] == 0.0f)
01093                 patch->mem[i + 4] = -feedbuffer[j + out_vertex_size * 1 + 6];
01094             if(patch->mem[i + 5] == 0.0f)
01095                 patch->mem[i + 5] = -feedbuffer[j + out_vertex_size * 1 + 7];
01096             normalize_normal(patch->mem + i + 3);
01097             i += d3d_out_vertex_size;
01098 
01099             if(patch->mem[i + 3] == 0.0f)
01100                 patch->mem[i + 3] = -feedbuffer[j + out_vertex_size * 0 + 5];
01101             if(patch->mem[i + 4] == 0.0f)
01102                 patch->mem[i + 4] = -feedbuffer[j + out_vertex_size * 0 + 6];
01103             if(patch->mem[i + 5] == 0.0f)
01104                 patch->mem[i + 5] = -feedbuffer[j + out_vertex_size * 0 + 7];
01105             normalize_normal(patch->mem + i + 3);
01106             i += d3d_out_vertex_size;
01107         }
01108     }
01109 
01110     glDisable(GL_MAP2_VERTEX_3);
01111     glDisable(GL_AUTO_NORMAL);
01112     glDisable(GL_MAP2_NORMAL);
01113     glDisable(GL_MAP2_TEXTURE_COORD_4);
01114     checkGLcall("glDisable vertex attrib generation");
01115     LEAVE_GL();
01116 
01117     context_release(context);
01118 
01119     HeapFree(GetProcessHeap(), 0, feedbuffer);
01120 
01121     vtxStride = 3 * sizeof(float);
01122     if(patch->has_normals) {
01123         vtxStride += 3 * sizeof(float);
01124     }
01125     if(patch->has_texcoords) {
01126         vtxStride += 4 * sizeof(float);
01127     }
01128     memset(&patch->strided, 0, sizeof(patch->strided));
01129     patch->strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
01130     patch->strided.position.data = (BYTE *)patch->mem;
01131     patch->strided.position.stride = vtxStride;
01132 
01133     if (patch->has_normals)
01134     {
01135         patch->strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
01136         patch->strided.normal.data = (BYTE *)patch->mem + 3 * sizeof(float) /* pos */;
01137         patch->strided.normal.stride = vtxStride;
01138     }
01139     if (patch->has_texcoords)
01140     {
01141         patch->strided.tex_coords[0].format = WINED3DFMT_R32G32B32A32_FLOAT;
01142         patch->strided.tex_coords[0].data = (BYTE *)patch->mem + 3 * sizeof(float) /* pos */;
01143         if (patch->has_normals)
01144             patch->strided.tex_coords[0].data += 3 * sizeof(float);
01145         patch->strided.tex_coords[0].stride = vtxStride;
01146     }
01147 
01148     return WINED3D_OK;
01149 }

Generated on Thu May 24 2012 04:22:33 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.