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

📄 drawprim.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
                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 + -