⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drawprim.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:

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 + -