📄 drawprim.c
字号:
static void depth_blt(IWineD3DDevice *iface, GLuint texture) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
GLint old_binding = 0;
glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_STENCIL_TEST);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glBlendFunc(GL_ZERO, GL_ONE);
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
glBindTexture(GL_TEXTURE_2D, texture);
glEnable(GL_TEXTURE_2D);
This->shader_backend->shader_select_depth_blt(iface);
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(-1.0f, -1.0f);
glVertex2f(1.0f, -1.0f);
glVertex2f(-1.0f, 1.0f);
glVertex2f(1.0f, 1.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D, old_binding);
glPopAttrib();
/* Reselect the old shaders. There doesn't seem to be any glPushAttrib bit for arb shaders,
* and this seems easier and more efficient than providing the shader backend with a private
* storage to read and restore the old shader settings
*/
This->shader_backend->shader_select(iface, use_ps(This), use_vs(This));
}
static void depth_copy(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *)This->depthStencilBuffer;
/* Only copy the depth buffer if there is one. */
if (!depth_stencil) return;
/* TODO: Make this work for modes other than FBO */
if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return;
if (depth_stencil->current_renderbuffer) {
FIXME("Not supported with fixed up depth stencil\n");
return;
}
if (This->render_offscreen) {
static GLuint tmp_texture = 0;
GLint old_binding = 0;
TRACE("Copying onscreen depth buffer to offscreen surface\n");
if (!tmp_texture) {
glGenTextures(1, &tmp_texture);
}
/* Note that we use depth_blt here as well, rather than glCopyTexImage2D
* directly on the FBO texture. That's because we need to flip. */
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
glBindTexture(GL_TEXTURE_2D, tmp_texture);
glCopyTexImage2D(depth_stencil->glDescription.target,
depth_stencil->glDescription.level,
depth_stencil->glDescription.glFormatInternal,
0,
0,
depth_stencil->currentDesc.Width,
depth_stencil->currentDesc.Height,
0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
glBindTexture(GL_TEXTURE_2D, old_binding);
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
checkGLcall("glBindFramebuffer()");
depth_blt(iface, tmp_texture);
checkGLcall("depth_blt");
} else {
TRACE("Copying offscreen surface to onscreen depth buffer\n");
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
checkGLcall("glBindFramebuffer()");
depth_blt(iface, depth_stencil->glDescription.textureName);
checkGLcall("depth_blt");
}
}
static inline void drawStridedInstanced(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd, UINT numberOfVertices,
GLenum glPrimitiveType, const void *idxData, short idxSize, ULONG minIndex,
ULONG startIdx, ULONG startVertex) {
UINT numInstances = 0;
int numInstancedAttribs = 0, i, j;
UINT instancedData[sizeof(sd->u.input) / sizeof(sd->u.input[0]) /* 16 */];
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
IWineD3DStateBlockImpl *stateblock = This->stateBlock;
if (idxSize == 0) {
/* This is a nasty thing. MSDN says no hardware supports that and apps have to use software vertex processing.
* We don't support this for now
*
* Shouldn't be too hard to support with opengl, in theory just call glDrawArrays instead of drawElements.
* But the StreamSourceFreq value has a different meaning in that situation.
*/
FIXME("Non-indexed instanced drawing is not supported\n");
return;
}
TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
idxData = idxData == (void *)-1 ? NULL : idxData;
/* First, figure out how many instances we have to draw */
for(i = 0; i < MAX_STREAMS; i++) {
/* Look at all non-instanced streams */
if(!(stateblock->streamFlags[i] & WINED3DSTREAMSOURCE_INSTANCEDATA) &&
stateblock->streamSource[i]) {
int inst = stateblock->streamFreq[i];
if(numInstances && inst != numInstances) {
ERR("Two streams specify a different number of instances. Got %d, new is %d\n", numInstances, inst);
}
numInstances = inst;
}
}
for(i = 0; i < sizeof(sd->u.input) / sizeof(sd->u.input[0]); i++) {
if(stateblock->streamFlags[sd->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
instancedData[numInstancedAttribs] = i;
numInstancedAttribs++;
}
}
/* now draw numInstances instances :-) */
for(i = 0; i < numInstances; i++) {
/* Specify the instanced attributes using immediate mode calls */
for(j = 0; j < numInstancedAttribs; j++) {
BYTE *ptr = sd->u.input[instancedData[j]].lpData +
sd->u.input[instancedData[j]].dwStride * i +
stateblock->streamOffset[sd->u.input[instancedData[j]].streamNo];
if(sd->u.input[instancedData[j]].VBO) {
IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[sd->u.input[instancedData[j]].streamNo];
ptr += (long) vb->resource.allocatedMemory;
}
switch(sd->u.input[instancedData[j]].dwType) {
case WINED3DDECLTYPE_FLOAT1:
GL_EXTCALL(glVertexAttrib1fvARB(instancedData[j], (float *) ptr));
break;
case WINED3DDECLTYPE_FLOAT2:
GL_EXTCALL(glVertexAttrib2fvARB(instancedData[j], (float *) ptr));
break;
case WINED3DDECLTYPE_FLOAT3:
GL_EXTCALL(glVertexAttrib3fvARB(instancedData[j], (float *) ptr));
break;
case WINED3DDECLTYPE_FLOAT4:
GL_EXTCALL(glVertexAttrib4fvARB(instancedData[j], (float *) ptr));
break;
case WINED3DDECLTYPE_UBYTE4:
GL_EXTCALL(glVertexAttrib4NubvARB(instancedData[j], ptr));
break;
case WINED3DDECLTYPE_UBYTE4N:
case WINED3DDECLTYPE_D3DCOLOR:
GL_EXTCALL(glVertexAttrib4NubvARB(instancedData[j], ptr));
break;
case WINED3DDECLTYPE_SHORT2:
GL_EXTCALL(glVertexAttrib4svARB(instancedData[j], (GLshort *) ptr));
break;
case WINED3DDECLTYPE_SHORT4:
GL_EXTCALL(glVertexAttrib4svARB(instancedData[j], (GLshort *) ptr));
break;
case WINED3DDECLTYPE_SHORT2N:
{
GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1};
GL_EXTCALL(glVertexAttrib4NsvARB(instancedData[j], s));
break;
}
case WINED3DDECLTYPE_USHORT2N:
{
GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1};
GL_EXTCALL(glVertexAttrib4NusvARB(instancedData[j], s));
break;
}
case WINED3DDECLTYPE_SHORT4N:
GL_EXTCALL(glVertexAttrib4NsvARB(instancedData[j], (GLshort *) ptr));
break;
case WINED3DDECLTYPE_USHORT4N:
GL_EXTCALL(glVertexAttrib4NusvARB(instancedData[j], (GLushort *) ptr));
break;
case WINED3DDECLTYPE_UDEC3:
FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
/*glVertexAttrib3usvARB(instancedData[j], (GLushort *) ptr); Does not exist */
break;
case WINED3DDECLTYPE_DEC3N:
FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
/*glVertexAttrib3NusvARB(instancedData[j], (GLushort *) ptr); Does not exist */
break;
case WINED3DDECLTYPE_FLOAT16_2:
/* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
* byte float according to the IEEE standard
*/
if (GL_SUPPORT(NV_HALF_FLOAT)) {
GL_EXTCALL(glVertexAttrib2hvNV(instancedData[j], (GLhalfNV *)ptr));
} else {
FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
}
break;
case WINED3DDECLTYPE_FLOAT16_4:
if (GL_SUPPORT(NV_HALF_FLOAT)) {
GL_EXTCALL(glVertexAttrib4hvNV(instancedData[j], (GLhalfNV *)ptr));
} else {
FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
}
break;
case WINED3DDECLTYPE_UNUSED:
default:
ERR("Unexpected declaration in instanced attributes\n");
break;
}
}
glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
(const char *)idxData+(idxSize * startIdx));
checkGLcall("glDrawElements");
}
}
struct coords {
int x, y, z;
};
void blt_to_drawable(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *surface) {
struct coords coords[4];
int low_coord;
/* TODO: This could be supported for lazy unlocking */
if(!(surface->Flags & SFLAG_INTEXTURE)) {
/* It is ok at init to be nowhere */
if(!(surface->Flags & SFLAG_INSYSMEM)) {
ERR("Blitting surfaces from sysmem not supported yet\n");
}
return;
}
ActivateContext(This, This->render_targets[0], CTXUSAGE_BLIT);
ENTER_GL();
if(surface->glDescription.target == GL_TEXTURE_2D) {
glBindTexture(GL_TEXTURE_2D, surface->glDescription.textureName);
checkGLcall("GL_TEXTURE_2D, This->glDescription.textureName)");
coords[0].x = 0; coords[0].y = 0; coords[0].z = 0;
coords[1].x = 0; coords[1].y = 1; coords[1].z = 0;
coords[2].x = 1; coords[2].y = 1; coords[2].z = 0;
coords[3].x = 1; coords[3].y = 0; coords[3].z = 0;
low_coord = 0;
} else {
/* Must be a cube map */
glDisable(GL_TEXTURE_2D);
checkGLcall("glDisable(GL_TEXTURE_2D)");
glEnable(GL_TEXTURE_CUBE_MAP_ARB);
checkGLcall("glEnable(surface->glDescription.target)");
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, surface->glDescription.textureName);
checkGLcall("GL_TEXTURE_CUBE_MAP_ARB, This->glDescription.textureName)");
switch(surface->glDescription.target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
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_X:
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_Y:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -