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

📄 device.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
    int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
    BOOL conv;

    if(Size == 0) {
        WARN("Size 0 requested, returning WINED3DERR_INVALIDCALL\n");
        *ppVertexBuffer = NULL;
        return WINED3DERR_INVALIDCALL;
    }

    D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)

    TRACE("(%p) : Size=%d, Usage=%d, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
    *ppVertexBuffer = (IWineD3DVertexBuffer *)object;

    if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
        object->resource.allocatedMemory  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
    }
    object->fvf = FVF;

    /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
     * drawStridedFast (half-life 2).
     *
     * Basically converting the vertices in the buffer is quite expensive, and observations
     * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
     * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
     *
     * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
     * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
     * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
     * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
     * dx7 apps.
     * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
     * more. In this call we can convert dx7 buffers too.
     */
    conv = ((FVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) || (FVF & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR));
    if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && 
        (dxVersion > 7 || !conv) ) {
        CreateVBO(object);
    }
    return WINED3D_OK;
}

static void CreateIndexBufferVBO(IWineD3DDeviceImpl *This, IWineD3DIndexBufferImpl *object) {
    GLenum error, glUsage;
    TRACE("Creating VBO for Index Buffer %p\n", object);

    /* The following code will modify the ELEMENT_ARRAY_BUFFER binding, make sure it is
     * restored on the next draw
     */
    IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);

    /* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */
    ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
    ENTER_GL();

    while(glGetError());

    GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
    error = glGetError();
    if(error != GL_NO_ERROR || object->vbo == 0) {
        ERR("Creating a vbo failed with error %s (%#x), continuing without vbo for this buffer\n", debug_glerror(error), error);
        goto out;
    }

    GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->vbo));
    error = glGetError();
    if(error != GL_NO_ERROR) {
        ERR("Failed to bind index buffer with error %s (%#x), continuing without vbo for this buffer\n", debug_glerror(error), error);
        goto out;
    }

    /* Use static write only usage for now. Dynamic index buffers stay in sysmem, and due to the sysmem
        * copy no readback will be needed
        */
    glUsage = GL_STATIC_DRAW_ARB;
    GL_EXTCALL(glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
    error = glGetError();
    if(error != GL_NO_ERROR) {
        ERR("Failed to initialize the index buffer with error %s (%#x)\n", debug_glerror(error), error);
        goto out;
    }
    LEAVE_GL();
    TRACE("Successfully created vbo %d for index buffer %p\n", object->vbo, object);
    return;

out:
    GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
    GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
    LEAVE_GL();
    object->vbo = 0;
}

static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage, 
                                                    WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
                                                    HANDLE *sharedHandle, IUnknown *parent) {
    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
    IWineD3DIndexBufferImpl *object;
    TRACE("(%p) Creating index buffer\n", This);

    /* Allocate the storage for the device */
    D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)

    if (Pool == WINED3DPOOL_DEFAULT ) { /* We need a local copy for drawStridedSlow */
        object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
    }

    if(Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
        CreateIndexBufferVBO(This, object);
    }

    TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format, 
                           debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
    *ppIndexBuffer = (IWineD3DIndexBuffer *) object;

    return WINED3D_OK;
}

static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {

    IWineD3DDeviceImpl     *This = (IWineD3DDeviceImpl *)iface;
    IWineD3DStateBlockImpl *object;
    int i, j;
    HRESULT temp_result;

    D3DCREATEOBJECTINSTANCE(object, StateBlock)
    object->blockType     = Type;

    for(i = 0; i < LIGHTMAP_SIZE; i++) {
        list_init(&object->lightMap[i]);
    }

    /* Special case - Used during initialization to produce a placeholder stateblock
          so other functions called can update a state block                         */
    if (Type == WINED3DSBT_INIT) {
        /* Don't bother increasing the reference count otherwise a device will never
           be freed due to circular dependencies                                   */
        return WINED3D_OK;
    }
    
    temp_result = allocate_shader_constants(object);
    if (WINED3D_OK != temp_result)
        return temp_result;

    /* Otherwise, might as well set the whole state block to the appropriate values  */
    if (This->stateBlock != NULL)
        stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
    else
        memset(object->streamFreq, 1, sizeof(object->streamFreq));

    /* Reset the ref and type after kludging it */
    object->wineD3DDevice = This;
    object->ref           = 1;
    object->blockType     = Type;

    TRACE("Updating changed flags appropriate for type %d\n", Type);

    if (Type == WINED3DSBT_ALL) {

        TRACE("ALL => Pretend everything has changed\n");
        stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);

        /* Lights are not part of the changed / set structure */
        for(j = 0; j < LIGHTMAP_SIZE; j++) {
            struct list *e;
            LIST_FOR_EACH(e, &object->lightMap[j]) {
                PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
                light->changed = TRUE;
                light->enabledChanged = TRUE;
            }
        }
        for(j = 1; j <= WINEHIGHEST_RENDER_STATE; j++) {
            object->contained_render_states[j - 1] = j;
        }
        /* TODO: Filter unused transforms between TEXTURE8 and WORLD0? */
        for(j = 1; j <= HIGHEST_TRANSFORMSTATE; j++) {
            object->contained_transform_states[j - 1] = j;
        }
        object->num_contained_transform_states = HIGHEST_TRANSFORMSTATE;
        for(j = 0; j < GL_LIMITS(vshader_constantsF); j++) {
            object->contained_vs_consts_f[j] = j;
        }
        object->num_contained_vs_consts_f = GL_LIMITS(vshader_constantsF);
        for(j = 0; j < MAX_CONST_I; j++) {
            object->contained_vs_consts_i[j] = j;
        }
        object->num_contained_vs_consts_i = MAX_CONST_I;
        for(j = 0; j < MAX_CONST_B; j++) {
            object->contained_vs_consts_b[j] = j;
        }
        object->num_contained_vs_consts_b = MAX_CONST_B;
        for(j = 0; j < GL_LIMITS(pshader_constantsF); j++) {
            object->contained_ps_consts_f[j] = j;
        }
        object->num_contained_ps_consts_f = GL_LIMITS(pshader_constantsF);
        for(j = 0; j < MAX_CONST_I; j++) {
            object->contained_ps_consts_i[j] = j;
        }
        object->num_contained_ps_consts_i = MAX_CONST_I;
        for(j = 0; j < MAX_CONST_B; j++) {
            object->contained_ps_consts_b[j] = j;
        }
        object->num_contained_ps_consts_b = MAX_CONST_B;
        for(i = 0; i < MAX_TEXTURES; i++) {
            for(j = 1; j <= WINED3D_HIGHEST_TEXTURE_STATE; j++) {
                object->contained_tss_states[object->num_contained_tss_states].stage = i;
                object->contained_tss_states[object->num_contained_tss_states].state = j;
                object->num_contained_tss_states++;
            }
        }
        for(i = 0; i < MAX_COMBINED_SAMPLERS; i++) {
            for(j = 1; j <= WINED3D_HIGHEST_SAMPLER_STATE; j++) {
                object->contained_sampler_states[object->num_contained_sampler_states].stage = i;
                object->contained_sampler_states[object->num_contained_sampler_states].state = j;
                object->num_contained_sampler_states++;
            }
        }

    } else if (Type == WINED3DSBT_PIXELSTATE) {

        TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
        stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);

        object->changed.pixelShader = TRUE;

        /* Pixel Shader Constants */
        for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
            object->contained_ps_consts_f[i] = i;
            object->changed.pixelShaderConstantsF[i] = TRUE;
        }
        object->num_contained_ps_consts_f = GL_LIMITS(vshader_constantsF);
        for (i = 0; i < MAX_CONST_B; ++i) {
            object->contained_ps_consts_b[i] = i;
            object->changed.pixelShaderConstantsB[i] = TRUE;
        }
        object->num_contained_ps_consts_b = MAX_CONST_B;
        for (i = 0; i < MAX_CONST_I; ++i) {
            object->contained_ps_consts_i[i] = i;
            object->changed.pixelShaderConstantsI[i] = TRUE;
        }
        object->num_contained_ps_consts_i = MAX_CONST_I;

        for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
            object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
            object->contained_render_states[i] = SavedPixelStates_R[i];
        }
        object->num_contained_render_states = NUM_SAVEDPIXELSTATES_R;
        for (j = 0; j < MAX_TEXTURES; j++) {
            for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
                object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
                object->contained_tss_states[object->num_contained_tss_states].stage = j;
                object->contained_tss_states[object->num_contained_tss_states].state = SavedPixelStates_T[i];
                object->num_contained_tss_states++;
            }
        }
        for (j = 0 ; j < MAX_COMBINED_SAMPLERS; j++) {
            for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
                object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
                object->contained_sampler_states[object->num_contained_sampler_states].stage = j;
                object->contained_sampler_states[object->num_contained_sampler_states].state = SavedPixelStates_S[i];
                object->num_contained_sampler_states++;
            }
        }

    } else if (Type == WINED3DSBT_VERTEXSTATE) {

        TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
        stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);

        object->changed.vertexShader = TRUE;

        /* Vertex Shader Constants */
        for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
            object->changed.vertexShaderConstantsF[i] = TRUE;
            object->contained_vs_consts_f[i] = i;
        }
        object->num_contained_vs_consts_f = GL_LIMITS(vshader_constantsF);
        for (i = 0; i < MAX_CONST_B; ++i) {
            object->changed.vertexShaderConstantsB[i] = TRUE;
            object->contained_vs_consts_b[i] = i;
        }
        object->num_contained_vs_consts_b = MAX_CONST_B;
        for (i = 0; i < MAX_CONST_I; ++i) {
            object->changed.vertexShaderConstantsI[i] = TRUE;
            object->contained_vs_consts_i[i] = i;
        }
        object->num_contained_vs_consts_i = MAX_CONST_I;
        for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
            object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
            object->contained_render_states[i] = SavedVertexStates_R[i];
        }
        object->num_contained_render_states = NUM_SAVEDVERTEXSTATES_R;
        for (j = 0; j < MAX_TEXTURES; j++) {
            for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
                object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
                object->contained_tss_states[object->num_contained_tss_states].stage = j;
                object->contained_tss_states[object->num_contained_tss_states].state = SavedVertexStates_T[i];
                object->num_contained_tss_states++;
            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -