📄 drawprim.c
字号:
coords[0].x = -1; coords[0].y = 1; coords[0].z = 1;
coords[1].x = 1; coords[1].y = 1; coords[1].z = 1;
coords[2].x = 1; coords[2].y = 1; coords[2].z = -1;
coords[3].x = -1; coords[3].y = 1; coords[3].z = -1;
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
coords[0].x = -1; coords[0].y = -1; coords[0].z = 1;
coords[1].x = 1; coords[1].y = -1; coords[1].z = 1;
coords[2].x = 1; coords[2].y = -1; coords[2].z = -1;
coords[3].x = -1; coords[3].y = -1; coords[3].z = -1;
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
coords[0].x = -1; coords[0].y = -1; coords[0].z = 1;
coords[1].x = 1; coords[1].y = -1; coords[1].z = 1;
coords[2].x = 1; coords[2].y = -1; coords[2].z = 1;
coords[3].x = -1; coords[3].y = -1; coords[3].z = 1;
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
coords[0].x = -1; coords[0].y = -1; coords[0].z = -1;
coords[1].x = 1; coords[1].y = -1; coords[1].z = -1;
coords[2].x = 1; coords[2].y = -1; coords[2].z = -1;
coords[3].x = -1; coords[3].y = -1; coords[3].z = -1;
default:
ERR("Unexpected texture target\n");
LEAVE_GL();
return;
}
low_coord = -1;
}
if(This->render_offscreen) {
coords[0].y = coords[0].y == 1 ? low_coord : 1;
coords[1].y = coords[1].y == 1 ? low_coord : 1;
coords[2].y = coords[2].y == 1 ? low_coord : 1;
coords[3].y = coords[3].y == 1 ? low_coord : 1;
}
glBegin(GL_QUADS);
glTexCoord3iv((GLint *) &coords[0]);
glVertex2i(0, 0);
glTexCoord3iv((GLint *) &coords[1]);
glVertex2i(0, surface->pow2Height);
glTexCoord3iv((GLint *) &coords[2]);
glVertex2i(surface->pow2Width, surface->pow2Height);
glTexCoord3iv((GLint *) &coords[3]);
glVertex2i(surface->pow2Width, 0);
glEnd();
checkGLcall("glEnd");
if(surface->glDescription.target != GL_TEXTURE_2D) {
glEnable(GL_TEXTURE_2D);
checkGLcall("glEnable(GL_TEXTURE_2D)");
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
}
LEAVE_GL();
}
/* Routine common to the draw primitive and draw indexed primitive routines */
void drawPrimitive(IWineD3DDevice *iface,
int PrimitiveType,
long NumPrimitives,
/* for Indexed: */
long StartVertexIndex,
UINT numberOfVertices,
long StartIdx,
short idxSize,
const void *idxData,
int minIndex) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DSwapChain *swapchain;
IWineD3DBaseTexture *texture = NULL;
IWineD3DSurfaceImpl *target;
int i;
/* Signals other modules that a drawing is in progress and the stateblock finalized */
This->isInDraw = TRUE;
/* Invalidate the back buffer memory so LockRect will read it the next time */
for(i = 0; i < GL_LIMITS(buffers); i++) {
target = (IWineD3DSurfaceImpl *) This->render_targets[i];
/* TODO: Only do all that if we're going to change anything
* Texture container dirtification does not work quite right yet
*/
if(target /*&& target->Flags & (SFLAG_INTEXTURE | SFLAG_INSYSMEM)*/) {
swapchain = NULL;
texture = NULL;
if(i == 0) {
IWineD3DSurface_GetContainer((IWineD3DSurface *) target, &IID_IWineD3DSwapChain, (void **)&swapchain);
/* Need the surface in the drawable! */
if(!(target->Flags & SFLAG_INDRAWABLE) && (swapchain || wined3d_settings.offscreen_rendering_mode != ORM_FBO)) {
blt_to_drawable(This, target);
}
if(swapchain) {
/* Onscreen target. Invalidate system memory copy and texture copy */
target->Flags &= ~(SFLAG_INSYSMEM | SFLAG_INTEXTURE);
target->Flags |= SFLAG_INDRAWABLE;
IWineD3DSwapChain_Release(swapchain);
} else if(wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
/* Non-FBO target: Invalidate system copy, texture copy and dirtify the container */
IWineD3DSurface_GetContainer((IWineD3DSurface *) target, &IID_IWineD3DBaseTexture, (void **)&texture);
if(texture) {
IWineD3DBaseTexture_SetDirty(texture, TRUE);
IWineD3DTexture_Release(texture);
}
target->Flags &= ~(SFLAG_INSYSMEM | SFLAG_INTEXTURE);
target->Flags |= SFLAG_INDRAWABLE;
} else {
/* FBO offscreen target. Invalidate system memory copy */
target->Flags &= ~SFLAG_INSYSMEM;
}
} else {
/* Must be an fbo render target */
target->Flags &= ~SFLAG_INSYSMEM;
target->Flags |= SFLAG_INTEXTURE;
}
}
}
/* Ok, we will be updating the screen from here onwards so grab the lock */
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
ENTER_GL();
apply_fbo_state(iface);
LEAVE_GL();
}
ActivateContext(This, This->render_targets[0], CTXUSAGE_DRAWPRIM);
ENTER_GL();
if (This->depth_copy_state == WINED3D_DCS_COPY) {
depth_copy(iface);
}
This->depth_copy_state = WINED3D_DCS_INITIAL;
{
GLenum glPrimType;
BOOL emulation = FALSE;
WineDirect3DVertexStridedData *strided = &This->strided_streams;
WineDirect3DVertexStridedData stridedlcl;
/* Ok, Work out which primitive is requested and how many vertexes that
will be */
UINT calculatedNumberOfindices = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
if (numberOfVertices == 0 )
numberOfVertices = calculatedNumberOfindices;
if(!This->strided_streams.u.s.position_transformed && !use_vs(This)) {
if(This->activeContext->num_untracked_materials &&
This->stateBlock->renderState[WINED3DRS_LIGHTING]) {
IWineD3DVertexBufferImpl *vb;
FIXME("Using software emulation because not all material properties could be tracked\n");
emulation = TRUE;
strided = &stridedlcl;
memcpy(&stridedlcl, &This->strided_streams, sizeof(stridedlcl));
#define FIXVBO(type) \
if(stridedlcl.u.s.type.VBO) { \
vb = (IWineD3DVertexBufferImpl *) This->stateBlock->streamSource[stridedlcl.u.s.type.streamNo]; \
stridedlcl.u.s.type.VBO = 0; \
stridedlcl.u.s.type.lpData = (BYTE *) ((unsigned long) stridedlcl.u.s.type.lpData + (unsigned long) vb->resource.allocatedMemory); \
}
FIXVBO(position);
FIXVBO(blendWeights);
FIXVBO(blendMatrixIndices);
FIXVBO(normal);
FIXVBO(pSize);
FIXVBO(diffuse);
FIXVBO(specular);
for(i = 0; i < WINED3DDP_MAXTEXCOORD; i++) FIXVBO(texCoords[i]);
FIXVBO(position2);
FIXVBO(normal2);
FIXVBO(tangent);
FIXVBO(binormal);
FIXVBO(tessFactor);
FIXVBO(fog);
FIXVBO(depth);
FIXVBO(sample);
#undef FIXVBO
}
}
if (This->useDrawStridedSlow || emulation) {
/* Immediate mode drawing */
drawStridedSlow(iface, strided, calculatedNumberOfindices,
glPrimType, idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
} else if(This->instancedDraw) {
/* Instancing emulation with mixing immediate mode and arrays */
drawStridedInstanced(iface, &This->strided_streams, calculatedNumberOfindices, glPrimType,
idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
} else {
/* Simple array draw call */
drawStridedFast(iface, calculatedNumberOfindices, glPrimType,
idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
}
}
/* Finshed updating the screen, restore lock */
LEAVE_GL();
TRACE("Done all gl drawing\n");
/* Diagnostics */
#ifdef SHOW_FRAME_MAKEUP
{
static long int primCounter = 0;
/* NOTE: set primCounter to the value reported by drawprim
before you want to to write frame makeup to /tmp */
if (primCounter >= 0) {
WINED3DLOCKED_RECT r;
char buffer[80];
IWineD3DSurface_LockRect(This->renderTarget, &r, NULL, WINED3DLOCK_READONLY);
sprintf(buffer, "/tmp/backbuffer_%d.tga", primCounter);
TRACE("Saving screenshot %s\n", buffer);
IWineD3DSurface_SaveSnapshot(This->renderTarget, buffer);
IWineD3DSurface_UnlockRect(This->renderTarget);
#ifdef SHOW_TEXTURE_MAKEUP
{
IWineD3DSurface *pSur;
int textureNo;
for (textureNo = 0; textureNo < MAX_COMBINED_SAMPLERS; ++textureNo) {
if (This->stateBlock->textures[textureNo] != NULL) {
sprintf(buffer, "/tmp/texture_%p_%d_%d.tga", This->stateBlock->textures[textureNo], primCounter, textureNo);
TRACE("Saving texture %s\n", buffer);
if (IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]) == WINED3DRTYPE_TEXTURE) {
IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[textureNo], 0, &pSur);
IWineD3DSurface_SaveSnapshot(pSur, buffer);
IWineD3DSurface_Release(pSur);
} else {
FIXME("base Texture isn't of type texture %d\n", IWineD3DBaseTexture_GetType(This->stateBlock->textures[textureNo]));
}
}
}
}
#endif
}
TRACE("drawprim #%d\n", primCounter);
++primCounter;
}
#endif
/* Control goes back to the device, stateblock values may change again */
This->isInDraw = FALSE;
}
static void normalize_normal(float *n) {
float length = n[0] * n[0] + n[1] * n[1] + n[2] * n[2];
if(length == 0.0) return;
length = sqrt(length);
n[0] = n[0] / length;
n[1] = n[1] / length;
n[2] = n[2] / length;
}
/* Tesselates a high order rectangular patch into single triangles using gl evaluators
*
* The problem is that OpenGL does not offer a direct way to return the tesselated primitives,
* and they can't be sent off for rendering directly either. Tesselating is slow, so we want
* to chache the patches in a vertex buffer. But more importantly, gl can't bind generated
* attributes to numbered shader attributes, so we have to store them and rebind them as needed
* in drawprim.
*
* To read back, the opengl feedback mode is used. This creates a proplem because we want
* untransformed, unlit vertices, but feedback runs everything through transform and lighting.
* Thus disable lighting and set identity matrices to get unmodified colors and positions.
* To overcome clipping find the biggest x, y and z values of the vertices in the patch and scale
* them to [-1.0;+1.0] and set the viewport up to scale them back.
*
* Normals are more tricky: Draw white vertices with 3 directional lights, and calculate the
* resulting colors back to the normals.
*
* NOTE: This function activates a context for blitting, modifies matrices & viewport, but
* does not restore it because normally a draw follows immediately afterwards. The caller is
* responsible of taking care that either the gl states are restored, or the context activated
* for drawing to reset the lastWasBlit flag.
*/
HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This,
struct WineD3DRectPatch *patch) {
unsigned int i, j, num_quads, out_vertex_size, buffer_size, d3d_out_vertex_size;
float max_x = 0.0, max_y = 0.0, max_z = 0.0, neg_z = 0.0;
WineDirect3DVertexStridedData strided;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -