📄 device.c
字号:
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 + -