wined3d: Use the context manager to create onscreen contexts.
This commit is contained in:
parent
00aa8ab08c
commit
f5f501d573
@ -54,13 +54,67 @@ static void Context_MarkStateDirty(WineD3DContext *context, DWORD state) {
|
||||
context->isStateDirty[idx] |= (1 << shift);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* AddContextToArray
|
||||
*
|
||||
* Adds a context to the context array. Helper function for CreateContext
|
||||
*
|
||||
* This method is not called in performance-critical code paths, only when a
|
||||
* new render target or swapchain is created. Thus performance is not an issue
|
||||
* here.
|
||||
*
|
||||
* Params:
|
||||
* This: Device to add the context for
|
||||
* display: X display this context uses
|
||||
* glCtx: glX context to add
|
||||
* drawable: drawable used with this context.
|
||||
*
|
||||
*****************************************************************************/
|
||||
static WineD3DContext *AddContextToArray(IWineD3DDeviceImpl *This, Display *display, GLXContext glCtx, Drawable drawable) {
|
||||
WineD3DContext **oldArray = This->contexts;
|
||||
DWORD state;
|
||||
|
||||
This->contexts = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->contexts) * (This->numContexts + 1));
|
||||
if(This->contexts == NULL) {
|
||||
ERR("Unable to grow the context array\n");
|
||||
This->contexts = oldArray;
|
||||
return NULL;
|
||||
}
|
||||
if(oldArray) {
|
||||
memcpy(This->contexts, oldArray, sizeof(*This->contexts) * This->numContexts);
|
||||
}
|
||||
|
||||
This->contexts[This->numContexts] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineD3DContext));
|
||||
if(This->contexts[This->numContexts] == NULL) {
|
||||
ERR("Unable to allocate a new context\n");
|
||||
HeapFree(GetProcessHeap(), 0, This->contexts);
|
||||
This->contexts = oldArray;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
This->contexts[This->numContexts]->display = display;
|
||||
This->contexts[This->numContexts]->glCtx = glCtx;
|
||||
This->contexts[This->numContexts]->drawable = drawable;
|
||||
HeapFree(GetProcessHeap(), 0, oldArray);
|
||||
|
||||
/* Mark all states dirty to force a proper initialization of the states on the first use of the context
|
||||
*/
|
||||
for(state = 0; state <= STATE_HIGHEST; state++) {
|
||||
Context_MarkStateDirty(This->contexts[This->numContexts], state);
|
||||
}
|
||||
|
||||
This->numContexts++;
|
||||
TRACE("Created context %p\n", This->contexts[This->numContexts - 1]);
|
||||
return This->contexts[This->numContexts - 1];
|
||||
}
|
||||
|
||||
/* Returns an array of compatible FBconfig(s).
|
||||
* The array must be freed with XFree. Requires ENTER_GL()
|
||||
*/
|
||||
static GLXFBConfig* pbuffer_find_fbconfigs(
|
||||
IWineD3DDeviceImpl* This,
|
||||
IWineD3DSwapChainImpl* implicitSwapchainImpl,
|
||||
IWineD3DSurfaceImpl* RenderSurface) {
|
||||
IWineD3DSurfaceImpl* RenderSurface,
|
||||
Display *display) {
|
||||
|
||||
GLXFBConfig* cfgs = NULL;
|
||||
int nCfgs = 0;
|
||||
@ -88,8 +142,8 @@ static GLXFBConfig* pbuffer_find_fbconfigs(
|
||||
D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
|
||||
PUSH1(None);
|
||||
TRACE("calling chooseFGConfig\n");
|
||||
cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
|
||||
DefaultScreen(implicitSwapchainImpl->display),
|
||||
cfgs = glXChooseFBConfig(display,
|
||||
DefaultScreen(display),
|
||||
attribs, &nCfgs);
|
||||
if (cfgs == NULL) {
|
||||
/* OK we didn't find the exact config, so use any reasonable match */
|
||||
@ -109,8 +163,8 @@ static GLXFBConfig* pbuffer_find_fbconfigs(
|
||||
TRACE("calling makeglcfg\n");
|
||||
D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
|
||||
PUSH1(None);
|
||||
cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
|
||||
DefaultScreen(implicitSwapchainImpl->display),
|
||||
cfgs = glXChooseFBConfig(display,
|
||||
DefaultScreen(display),
|
||||
attribs, &nCfgs);
|
||||
}
|
||||
|
||||
@ -126,19 +180,6 @@ static GLXFBConfig* pbuffer_find_fbconfigs(
|
||||
debug_d3dformat(BackBufferFormat), StencilBufferFormat,
|
||||
debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
|
||||
}
|
||||
if (NULL != This->renderTarget) {
|
||||
glFlush();
|
||||
vcheckGLcall("glFlush");
|
||||
/** This is only useful if the old render target was a swapchain,
|
||||
* we need to supercede this with a function that displays
|
||||
* the current buffer on the screen. This is easy to do in glx1.3 but
|
||||
* we need to do copy-write pixels in glx 1.2.
|
||||
************************************************/
|
||||
glXSwapBuffers(implicitSwapChainImpl->display,
|
||||
implicitSwapChainImpl->drawable);
|
||||
printf("Hit Enter to get next frame ...\n");
|
||||
getchar();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#undef PUSH1
|
||||
@ -151,21 +192,20 @@ static GLXFBConfig* pbuffer_find_fbconfigs(
|
||||
* CreateContext
|
||||
*
|
||||
* Creates a new context for a window, or a pbuffer context.
|
||||
* TODO: Merge this with AddContext
|
||||
*
|
||||
* Params:
|
||||
* * Params:
|
||||
* This: Device to activate the context for
|
||||
* target: Surface this context will render to
|
||||
* display: X11 connection
|
||||
* win: Taget window. NULL for a pbuffer
|
||||
*
|
||||
*****************************************************************************/
|
||||
WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, Window win) {
|
||||
WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, Display *display, Window win) {
|
||||
Drawable drawable = win, oldDrawable;
|
||||
XVisualInfo *visinfo = NULL;
|
||||
GLXFBConfig *cfgs = NULL;
|
||||
GLXContext ctx = NULL, oldCtx;
|
||||
WineD3DContext *ret = NULL;
|
||||
IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) This->swapchains[0];
|
||||
|
||||
TRACE("(%p): Creating a %s context for render target %p\n", This, win ? "onscreen" : "offscreen", target);
|
||||
|
||||
@ -175,7 +215,7 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
|
||||
|
||||
TRACE("Creating a pBuffer drawable for the new context\n");
|
||||
|
||||
cfgs = pbuffer_find_fbconfigs(This, swapchain, target);
|
||||
cfgs = pbuffer_find_fbconfigs(This, target, display);
|
||||
if(!cfgs) {
|
||||
ERR("Cannot find a frame buffer configuration for the pbuffer\n");
|
||||
goto out;
|
||||
@ -187,13 +227,13 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
|
||||
attribs[nAttribs++] = target->currentDesc.Height;
|
||||
attribs[nAttribs++] = None;
|
||||
|
||||
visinfo = glXGetVisualFromFBConfig(swapchain->display, cfgs[0]);
|
||||
visinfo = glXGetVisualFromFBConfig(display, cfgs[0]);
|
||||
if(!visinfo) {
|
||||
ERR("Cannot find a visual for the pbuffer\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
drawable = glXCreatePbuffer(swapchain->display, cfgs[0], attribs);
|
||||
drawable = glXCreatePbuffer(display, cfgs[0], attribs);
|
||||
|
||||
if(!drawable) {
|
||||
ERR("Cannot create a pbuffer\n");
|
||||
@ -201,31 +241,83 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
|
||||
}
|
||||
XFree(cfgs);
|
||||
cfgs = NULL;
|
||||
} else {
|
||||
/* Create an onscreen target */
|
||||
XVisualInfo template;
|
||||
int num;
|
||||
|
||||
template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
|
||||
/* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
|
||||
(or the best possible if none is requested) */
|
||||
TRACE("Found x visual ID : %ld\n", template.visualid);
|
||||
visinfo = XGetVisualInfo(display, VisualIDMask, &template, &num);
|
||||
|
||||
if (NULL == visinfo) {
|
||||
ERR("cannot really get XVisual\n");
|
||||
goto out;
|
||||
} else {
|
||||
int n, value;
|
||||
/* Write out some debug info about the visual/s */
|
||||
TRACE("Using x visual ID : %ld\n", template.visualid);
|
||||
TRACE(" visual info: %p\n", visinfo);
|
||||
TRACE(" num items : %d\n", num);
|
||||
for (n = 0;n < num; n++) {
|
||||
TRACE("=====item=====: %d\n", n + 1);
|
||||
TRACE(" visualid : %ld\n", visinfo[n].visualid);
|
||||
TRACE(" screen : %d\n", visinfo[n].screen);
|
||||
TRACE(" depth : %u\n", visinfo[n].depth);
|
||||
TRACE(" class : %d\n", visinfo[n].class);
|
||||
TRACE(" red_mask : %ld\n", visinfo[n].red_mask);
|
||||
TRACE(" green_mask : %ld\n", visinfo[n].green_mask);
|
||||
TRACE(" blue_mask : %ld\n", visinfo[n].blue_mask);
|
||||
TRACE(" colormap_size : %d\n", visinfo[n].colormap_size);
|
||||
TRACE(" bits_per_rgb : %d\n", visinfo[n].bits_per_rgb);
|
||||
/* log some extra glx info */
|
||||
glXGetConfig(display, visinfo, GLX_AUX_BUFFERS, &value);
|
||||
TRACE(" gl_aux_buffers : %d\n", value);
|
||||
glXGetConfig(display, visinfo, GLX_BUFFER_SIZE ,&value);
|
||||
TRACE(" gl_buffer_size : %d\n", value);
|
||||
glXGetConfig(display, visinfo, GLX_RED_SIZE, &value);
|
||||
TRACE(" gl_red_size : %d\n", value);
|
||||
glXGetConfig(display, visinfo, GLX_GREEN_SIZE, &value);
|
||||
TRACE(" gl_green_size : %d\n", value);
|
||||
glXGetConfig(display, visinfo, GLX_BLUE_SIZE, &value);
|
||||
TRACE(" gl_blue_size : %d\n", value);
|
||||
glXGetConfig(display, visinfo, GLX_ALPHA_SIZE, &value);
|
||||
TRACE(" gl_alpha_size : %d\n", value);
|
||||
glXGetConfig(display, visinfo, GLX_DEPTH_SIZE ,&value);
|
||||
TRACE(" gl_depth_size : %d\n", value);
|
||||
glXGetConfig(display, visinfo, GLX_STENCIL_SIZE, &value);
|
||||
TRACE(" gl_stencil_size : %d\n", value);
|
||||
}
|
||||
/* Now choose a similar visual ID*/
|
||||
}
|
||||
}
|
||||
|
||||
ctx = glXCreateContext(swapchain->display, visinfo,
|
||||
ctx = glXCreateContext(display, visinfo,
|
||||
This->numContexts ? This->contexts[0]->glCtx : NULL,
|
||||
GL_TRUE);
|
||||
if(!ctx) {
|
||||
ERR("Failed to create a glX context\n");
|
||||
if(drawable != win) glXDestroyPbuffer(swapchain->display, drawable);
|
||||
if(drawable != win) glXDestroyPbuffer(display, drawable);
|
||||
goto out;
|
||||
}
|
||||
ret = AddContext(This, ctx, drawable);
|
||||
ret = AddContextToArray(This, display, ctx, drawable);
|
||||
if(!ret) {
|
||||
ERR("Failed to add the newly created context to the context list\n");
|
||||
glXDestroyContext(swapchain->display, ctx);
|
||||
if(drawable != win) glXDestroyPbuffer(swapchain->display, drawable);
|
||||
glXDestroyContext(display, ctx);
|
||||
if(drawable != win) glXDestroyPbuffer(display, drawable);
|
||||
goto out;
|
||||
}
|
||||
ret->surface = (IWineD3DSurface *) target;
|
||||
ret->isPBuffer = win == 0;
|
||||
|
||||
TRACE("Successfully created new context %p\n", ret);
|
||||
|
||||
/* Set up the context defaults */
|
||||
oldCtx = glXGetCurrentContext();
|
||||
oldDrawable = glXGetCurrentDrawable();
|
||||
if(glXMakeCurrent(swapchain->display, drawable, ctx) == FALSE) {
|
||||
if(glXMakeCurrent(display, drawable, ctx) == FALSE) {
|
||||
ERR("Cannot activate context to set up defaults\n");
|
||||
goto out;
|
||||
}
|
||||
@ -260,7 +352,9 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);
|
||||
checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);");
|
||||
|
||||
glXMakeCurrent(swapchain->display, oldDrawable, oldCtx);
|
||||
if(oldDrawable && oldCtx) {
|
||||
glXMakeCurrent(display, oldDrawable, oldCtx);
|
||||
}
|
||||
|
||||
out:
|
||||
if(visinfo) XFree(visinfo);
|
||||
@ -268,11 +362,51 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* RemoveContextFromArray
|
||||
*
|
||||
* Removes a context from the context manager. The opengl context is not
|
||||
* destroyed or unset. context is not a valid pointer after that call.
|
||||
*
|
||||
* Simmilar to the former call this isn't a performance critical function. A
|
||||
* helper function for DestroyContext.
|
||||
*
|
||||
* Params:
|
||||
* This: Device to activate the context for
|
||||
* context: Context to remove
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void RemoveContextFromArray(IWineD3DDeviceImpl *This, WineD3DContext *context) {
|
||||
UINT t, s;
|
||||
WineD3DContext **oldArray = This->contexts;
|
||||
|
||||
TRACE("Removing ctx %p\n", context);
|
||||
|
||||
This->numContexts--;
|
||||
|
||||
if(This->numContexts) {
|
||||
This->contexts = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->contexts) * This->numContexts);
|
||||
if(!This->contexts) {
|
||||
ERR("Cannot allocate a new context array, PANIC!!!\n");
|
||||
}
|
||||
t = 0;
|
||||
for(s = 0; s < This->numContexts; s++) {
|
||||
if(oldArray[s] == context) continue;
|
||||
This->contexts[t] = oldArray[s];
|
||||
t++;
|
||||
}
|
||||
} else {
|
||||
This->contexts = NULL;
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, context);
|
||||
HeapFree(GetProcessHeap(), 0, oldArray);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* DestroyContext
|
||||
*
|
||||
* Destroys a wineD3DContext
|
||||
* TODO: Merge with DeleteContext
|
||||
*
|
||||
* Params:
|
||||
* This: Device to activate the context for
|
||||
@ -280,12 +414,18 @@ out:
|
||||
*
|
||||
*****************************************************************************/
|
||||
void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context) {
|
||||
IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) This->swapchains[0];
|
||||
|
||||
glXDestroyContext(swapchain->display, context->glCtx);
|
||||
/* Assume pbuffer for now*/
|
||||
glXDestroyPbuffer(swapchain->display, context->drawable);
|
||||
DeleteContext(This, context);
|
||||
/* check that we are the current context first */
|
||||
TRACE("Destroying ctx %p\n", context);
|
||||
if(glXGetCurrentContext() == context->glCtx){
|
||||
glXMakeCurrent(context->display, None, NULL);
|
||||
}
|
||||
|
||||
glXDestroyContext(context->display, context->glCtx);
|
||||
if(context->isPBuffer) {
|
||||
glXDestroyPbuffer(context->display, context->drawable);
|
||||
}
|
||||
RemoveContextFromArray(This, context);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -515,7 +655,13 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
|
||||
if(This->pbufferContext) {
|
||||
DestroyContext(This, This->pbufferContext);
|
||||
}
|
||||
This->pbufferContext = CreateContext(This, targetimpl, 0 /* Window */);
|
||||
|
||||
/* The display is irrelevant here, the window is 0. But CreateContext needs a valid X connection.
|
||||
* Create the context on the same server as the primary swapchain. The primary swapchain is exists at this point.
|
||||
*/
|
||||
This->pbufferContext = CreateContext(This, targetimpl,
|
||||
((IWineD3DSwapChainImpl *) This->swapchains[0])->context->display,
|
||||
0 /* Window */);
|
||||
This->pbufferWidth = targetimpl->currentDesc.Width;
|
||||
This->pbufferHeight = targetimpl->currentDesc.Height;
|
||||
}
|
||||
@ -568,7 +714,7 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
|
||||
if(context != This->activeContext) {
|
||||
Bool ret;
|
||||
TRACE("Switching gl ctx to %p, drawable=%ld, ctx=%p\n", context, context->drawable, context->glCtx);
|
||||
ret = glXMakeCurrent(((IWineD3DSwapChainImpl *) This->swapchains[0])->display, context->drawable, context->glCtx);
|
||||
ret = glXMakeCurrent(context->display, context->drawable, context->glCtx);
|
||||
if(ret == FALSE) {
|
||||
ERR("Failed to activate the new context\n");
|
||||
}
|
||||
@ -603,99 +749,3 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
|
||||
FIXME("Unexpected context usage requested\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* AddContext
|
||||
*
|
||||
* Adds a new WineD3DContext keeping track of a glx context and drawable.
|
||||
* Creating the context and drawable is up to the swapchain or texture. This
|
||||
* function adds it to the context array to allow ActivateContext to find it
|
||||
* and keep track of dirty states. (Later on it will also be able to duplicate
|
||||
* the context for another thread).
|
||||
*
|
||||
* This method is not called in performance-critical code paths, only when a
|
||||
* new render target or swapchain is created. Thus performance is not an issue
|
||||
* here.
|
||||
*
|
||||
* Params:
|
||||
* This: Device to add the context for
|
||||
* glCtx: glX context to add
|
||||
* drawable: drawable used with this context.
|
||||
*
|
||||
*****************************************************************************/
|
||||
WineD3DContext *AddContext(IWineD3DDeviceImpl *This, GLXContext glCtx, Drawable drawable) {
|
||||
WineD3DContext **oldArray = This->contexts;
|
||||
DWORD state;
|
||||
|
||||
This->contexts = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->contexts) * (This->numContexts + 1));
|
||||
if(This->contexts == NULL) {
|
||||
ERR("Unable to grow the context array\n");
|
||||
This->contexts = oldArray;
|
||||
return NULL;
|
||||
}
|
||||
if(oldArray) {
|
||||
memcpy(This->contexts, oldArray, sizeof(*This->contexts) * This->numContexts);
|
||||
}
|
||||
|
||||
This->contexts[This->numContexts] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineD3DContext));
|
||||
if(This->contexts[This->numContexts] == NULL) {
|
||||
ERR("Unable to allocate a new context\n");
|
||||
HeapFree(GetProcessHeap(), 0, This->contexts);
|
||||
This->contexts = oldArray;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
This->contexts[This->numContexts]->glCtx = glCtx;
|
||||
This->contexts[This->numContexts]->drawable = drawable;
|
||||
HeapFree(GetProcessHeap(), 0, oldArray);
|
||||
|
||||
/* Mark all states dirty to force a proper initialization of the states on the first use of the context
|
||||
*/
|
||||
for(state = 0; state <= STATE_HIGHEST; state++) {
|
||||
Context_MarkStateDirty(This->contexts[This->numContexts], state);
|
||||
}
|
||||
|
||||
This->numContexts++;
|
||||
TRACE("Created context %p\n", This->contexts[This->numContexts - 1]);
|
||||
return This->contexts[This->numContexts - 1];
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* DeleteContext
|
||||
*
|
||||
* Removes a context from the context manager. The opengl context is not
|
||||
* destroyed or unset. context is not a valid pointer after that call.
|
||||
*
|
||||
* Simmilar to the former call this isn't a performance critical function.
|
||||
*
|
||||
* Params:
|
||||
* This: Device to activate the context for
|
||||
* context: Context to remove
|
||||
*
|
||||
*****************************************************************************/
|
||||
void DeleteContext(IWineD3DDeviceImpl *This, WineD3DContext *context) {
|
||||
UINT t, s;
|
||||
WineD3DContext **oldArray = This->contexts;
|
||||
|
||||
TRACE("Removing ctx %p\n", context);
|
||||
|
||||
This->numContexts--;
|
||||
|
||||
if(This->numContexts) {
|
||||
This->contexts = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->contexts) * This->numContexts);
|
||||
if(!This->contexts) {
|
||||
ERR("Cannot allocate a new context array, PANIC!!!\n");
|
||||
}
|
||||
t = 0;
|
||||
for(s = 0; s < This->numContexts; s++) {
|
||||
if(oldArray[s] == context) continue;
|
||||
This->contexts[t] = oldArray[s];
|
||||
t++;
|
||||
}
|
||||
} else {
|
||||
This->contexts = NULL;
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, context);
|
||||
HeapFree(GetProcessHeap(), 0, oldArray);
|
||||
}
|
||||
|
@ -1347,11 +1347,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic
|
||||
|
||||
HDC hDc;
|
||||
IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
|
||||
int num;
|
||||
XVisualInfo template;
|
||||
GLXContext oldContext, newCtx;
|
||||
Drawable oldDrawable;
|
||||
HRESULT hr = WINED3D_OK;
|
||||
IUnknown *bufferParent;
|
||||
Display *display;
|
||||
|
||||
TRACE("(%p) : Created Aditional Swap Chain\n", This);
|
||||
|
||||
@ -1386,11 +1384,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic
|
||||
return WINED3DERR_NOTAVAILABLE;
|
||||
}
|
||||
hDc = GetDC(object->win_handle);
|
||||
object->display = get_display(hDc);
|
||||
display = get_display(hDc);
|
||||
ReleaseDC(object->win_handle, hDc);
|
||||
TRACE("Using a display of %p %p\n", object->display, hDc);
|
||||
TRACE("Using a display of %p %p\n", display, hDc);
|
||||
|
||||
if (NULL == object->display || NULL == hDc) {
|
||||
if (NULL == display || NULL == hDc) {
|
||||
WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
|
||||
return WINED3DERR_NOTAVAILABLE;
|
||||
}
|
||||
@ -1403,6 +1401,63 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic
|
||||
object->orig_width = GetSystemMetrics(SM_CXSCREEN);
|
||||
object->orig_height = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
/** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
|
||||
* then the corresponding dimension of the client area of the hDeviceWindow
|
||||
* (or the focus window, if hDeviceWindow is NULL) is taken.
|
||||
**********************/
|
||||
|
||||
if (*(pPresentationParameters->Windowed) &&
|
||||
((*(pPresentationParameters->BackBufferWidth) == 0) ||
|
||||
(*(pPresentationParameters->BackBufferHeight) == 0))) {
|
||||
|
||||
RECT Rect;
|
||||
GetClientRect(object->win_handle, &Rect);
|
||||
|
||||
if (*(pPresentationParameters->BackBufferWidth) == 0) {
|
||||
*(pPresentationParameters->BackBufferWidth) = Rect.right;
|
||||
TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
|
||||
}
|
||||
if (*(pPresentationParameters->BackBufferHeight) == 0) {
|
||||
*(pPresentationParameters->BackBufferHeight) = Rect.bottom;
|
||||
TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
|
||||
}
|
||||
}
|
||||
|
||||
/* Put the correct figures in the presentation parameters */
|
||||
TRACE("Copying across presentation parameters\n");
|
||||
object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
|
||||
object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
|
||||
object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
|
||||
object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
|
||||
object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
|
||||
object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
|
||||
object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
|
||||
object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
|
||||
object->presentParms.Windowed = *(pPresentationParameters->Windowed);
|
||||
object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
|
||||
object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
|
||||
object->presentParms.Flags = *(pPresentationParameters->Flags);
|
||||
object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
|
||||
object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
|
||||
|
||||
TRACE("calling rendertarget CB\n");
|
||||
hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
|
||||
parent,
|
||||
object->presentParms.BackBufferWidth,
|
||||
object->presentParms.BackBufferHeight,
|
||||
object->presentParms.BackBufferFormat,
|
||||
object->presentParms.MultiSampleType,
|
||||
object->presentParms.MultiSampleQuality,
|
||||
TRUE /* Lockable */,
|
||||
&object->frontBuffer,
|
||||
NULL /* pShared (always null)*/);
|
||||
if (object->frontBuffer != NULL) {
|
||||
IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
|
||||
} else {
|
||||
ERR("Failed to create the front buffer\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an opengl context for the display visual
|
||||
* NOTE: the visual is chosen as the window is created and the glcontext cannot
|
||||
@ -1413,84 +1468,16 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic
|
||||
|
||||
/** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
|
||||
ENTER_GL();
|
||||
|
||||
/* Create a new context for this swapchain */
|
||||
template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
|
||||
/* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
|
||||
(or the best possible if none is requested) */
|
||||
TRACE("Found x visual ID : %ld\n", template.visualid);
|
||||
|
||||
object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
|
||||
if (NULL == object->visInfo) {
|
||||
ERR("cannot really get XVisual\n");
|
||||
LEAVE_GL();
|
||||
return WINED3DERR_NOTAVAILABLE;
|
||||
} else {
|
||||
int n, value;
|
||||
/* Write out some debug info about the visual/s */
|
||||
TRACE("Using x visual ID : %ld\n", template.visualid);
|
||||
TRACE(" visual info: %p\n", object->visInfo);
|
||||
TRACE(" num items : %d\n", num);
|
||||
for (n = 0;n < num; n++) {
|
||||
TRACE("=====item=====: %d\n", n + 1);
|
||||
TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
|
||||
TRACE(" screen : %d\n", object->visInfo[n].screen);
|
||||
TRACE(" depth : %u\n", object->visInfo[n].depth);
|
||||
TRACE(" class : %d\n", object->visInfo[n].class);
|
||||
TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
|
||||
TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
|
||||
TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
|
||||
TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
|
||||
TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
|
||||
/* log some extra glx info */
|
||||
glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
|
||||
TRACE(" gl_aux_buffers : %d\n", value);
|
||||
glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
|
||||
TRACE(" gl_buffer_size : %d\n", value);
|
||||
glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
|
||||
TRACE(" gl_red_size : %d\n", value);
|
||||
glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
|
||||
TRACE(" gl_green_size : %d\n", value);
|
||||
glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
|
||||
TRACE(" gl_blue_size : %d\n", value);
|
||||
glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
|
||||
TRACE(" gl_alpha_size : %d\n", value);
|
||||
glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
|
||||
TRACE(" gl_depth_size : %d\n", value);
|
||||
glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
|
||||
TRACE(" gl_stencil_size : %d\n", value);
|
||||
}
|
||||
/* Now choose a similar visual ID*/
|
||||
}
|
||||
|
||||
{
|
||||
IWineD3DSwapChain *implSwapChain;
|
||||
if (WINED3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
|
||||
/* The first time around we create the context that is shared with all other swapchains and render targets */
|
||||
newCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
|
||||
TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
|
||||
} else {
|
||||
|
||||
TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
|
||||
/* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
|
||||
/* and create a new context with the implicit swapchains context as the shared context */
|
||||
newCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->context->glCtx, GL_TRUE);
|
||||
IWineD3DSwapChain_Release(implSwapChain);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup */
|
||||
XFree(object->visInfo);
|
||||
object->visInfo = NULL;
|
||||
|
||||
object->context = CreateContext(This, (IWineD3DSurfaceImpl *) object->frontBuffer, display, object->win);
|
||||
LEAVE_GL();
|
||||
|
||||
if (!newCtx) {
|
||||
ERR("Failed to create GLX context\n");
|
||||
return WINED3DERR_NOTAVAILABLE;
|
||||
if (!object->context) {
|
||||
ERR("Failed to create a new context\n");
|
||||
hr = WINED3DERR_NOTAVAILABLE;
|
||||
goto error;
|
||||
} else {
|
||||
TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
|
||||
object->win_handle, newCtx, object->win, object->visInfo);
|
||||
TRACE("Context created (HWND=%p, glContext=%p, Window=%ld)\n",
|
||||
object->win_handle, object->context->glCtx, object->win);
|
||||
}
|
||||
|
||||
/*********************
|
||||
@ -1536,86 +1523,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic
|
||||
ClipCursor(&clip_rc);
|
||||
}
|
||||
|
||||
|
||||
/** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
|
||||
* then the corresponding dimension of the client area of the hDeviceWindow
|
||||
* (or the focus window, if hDeviceWindow is NULL) is taken.
|
||||
**********************/
|
||||
|
||||
if (*(pPresentationParameters->Windowed) &&
|
||||
((*(pPresentationParameters->BackBufferWidth) == 0) ||
|
||||
(*(pPresentationParameters->BackBufferHeight) == 0))) {
|
||||
|
||||
RECT Rect;
|
||||
GetClientRect(object->win_handle, &Rect);
|
||||
|
||||
if (*(pPresentationParameters->BackBufferWidth) == 0) {
|
||||
*(pPresentationParameters->BackBufferWidth) = Rect.right;
|
||||
TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
|
||||
}
|
||||
if (*(pPresentationParameters->BackBufferHeight) == 0) {
|
||||
*(pPresentationParameters->BackBufferHeight) = Rect.bottom;
|
||||
TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
|
||||
}
|
||||
}
|
||||
|
||||
/*********************
|
||||
* finish off parameter initialization
|
||||
*******************/
|
||||
|
||||
/* Put the correct figures in the presentation parameters */
|
||||
TRACE("Copying across presentation parameters\n");
|
||||
object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
|
||||
object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
|
||||
object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
|
||||
object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
|
||||
object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
|
||||
object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
|
||||
object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
|
||||
object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
|
||||
object->presentParms.Windowed = *(pPresentationParameters->Windowed);
|
||||
object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
|
||||
object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
|
||||
object->presentParms.Flags = *(pPresentationParameters->Flags);
|
||||
object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
|
||||
object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
|
||||
|
||||
|
||||
/*********************
|
||||
* Create the back, front and stencil buffers
|
||||
*******************/
|
||||
|
||||
TRACE("calling rendertarget CB\n");
|
||||
hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
|
||||
parent,
|
||||
object->presentParms.BackBufferWidth,
|
||||
object->presentParms.BackBufferHeight,
|
||||
object->presentParms.BackBufferFormat,
|
||||
object->presentParms.MultiSampleType,
|
||||
object->presentParms.MultiSampleQuality,
|
||||
TRUE /* Lockable */,
|
||||
&object->frontBuffer,
|
||||
NULL /* pShared (always null)*/);
|
||||
if (object->frontBuffer != NULL)
|
||||
IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
|
||||
|
||||
if(object->presentParms.BackBufferCount > 0) {
|
||||
int i;
|
||||
|
||||
object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
|
||||
if(!object->backBuffer) {
|
||||
ERR("Out of memory\n");
|
||||
|
||||
if (object->frontBuffer) {
|
||||
IUnknown *bufferParent;
|
||||
IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
|
||||
IUnknown_Release(bufferParent); /* once for the get parent */
|
||||
if (IUnknown_Release(bufferParent) > 0) {
|
||||
FIXME("(%p) Something's still holding the front buffer\n",This);
|
||||
}
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, object);
|
||||
return E_OUTOFMEMORY;
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto error;
|
||||
}
|
||||
|
||||
for(i = 0; i < object->presentParms.BackBufferCount; i++) {
|
||||
@ -1633,19 +1551,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic
|
||||
if(hr == WINED3D_OK && object->backBuffer[i]) {
|
||||
IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
|
||||
} else {
|
||||
break;
|
||||
ERR("Cannot create new back buffer\n");
|
||||
goto error;
|
||||
}
|
||||
ENTER_GL();
|
||||
glDrawBuffer(GL_BACK);
|
||||
checkGLcall("glDrawBuffer(GL_BACK)");
|
||||
LEAVE_GL();
|
||||
}
|
||||
} else {
|
||||
object->backBuffer = NULL;
|
||||
}
|
||||
|
||||
if (object->backBuffer != NULL) {
|
||||
ENTER_GL();
|
||||
glDrawBuffer(GL_BACK);
|
||||
checkGLcall("glDrawBuffer(GL_BACK)");
|
||||
LEAVE_GL();
|
||||
} else {
|
||||
/* Single buffering - draw to front buffer */
|
||||
ENTER_GL();
|
||||
glDrawBuffer(GL_FRONT);
|
||||
@ -1679,108 +1595,36 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic
|
||||
object->wantsDepthStencilBuffer = FALSE;
|
||||
}
|
||||
|
||||
TRACE("Created swapchain %p\n", object);
|
||||
TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
|
||||
return WINED3D_OK;
|
||||
|
||||
|
||||
/*********************
|
||||
* init the default renderTarget management
|
||||
*******************/
|
||||
object->render_ctx = newCtx;
|
||||
|
||||
/* Register the context */
|
||||
object->context = AddContext(This, newCtx, object->win);
|
||||
|
||||
if (hr == WINED3D_OK && object->context) {
|
||||
/*********************
|
||||
* Setup some defaults and clear down the buffers
|
||||
*******************/
|
||||
ENTER_GL();
|
||||
/** save current context and drawable **/
|
||||
oldContext = glXGetCurrentContext();
|
||||
oldDrawable = glXGetCurrentDrawable();
|
||||
|
||||
TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, newCtx, object->win);
|
||||
if (glXMakeCurrent(object->display, object->win, newCtx) == False) {
|
||||
ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, newCtx, object->win);
|
||||
}
|
||||
checkGLcall("glXMakeCurrent");
|
||||
|
||||
TRACE("Setting up the screen\n");
|
||||
/* Clear the screen */
|
||||
glClearColor(1.0, 0.0, 0.0, 0.0);
|
||||
checkGLcall("glClearColor");
|
||||
glClearIndex(0);
|
||||
glClearDepth(1);
|
||||
glClearStencil(0xffff);
|
||||
|
||||
checkGLcall("glClear");
|
||||
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
checkGLcall("glColor3f");
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
checkGLcall("glEnable");
|
||||
|
||||
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
|
||||
checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
|
||||
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
|
||||
checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
|
||||
|
||||
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
|
||||
checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
|
||||
|
||||
/* switch back to the original context (if there was one)*/
|
||||
if (This->swapchains) {
|
||||
/** TODO: restore the context and drawable **/
|
||||
glXMakeCurrent(object->display, oldDrawable, oldContext);
|
||||
}
|
||||
|
||||
/* Set the surface alignment. This never changes, so we are safe to set it once per context*/
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);
|
||||
checkGLcall("glPixelStorei(GL_PACK_ALIGNMENT, SURFACE_ALIGNMENT);");
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);
|
||||
checkGLcall("glPixelStorei(GL_UNPACK_ALIGNMENT, SURFACE_ALIGNMENT);");
|
||||
|
||||
LEAVE_GL();
|
||||
|
||||
TRACE("Set swapchain to %p\n", object);
|
||||
} else { /* something went wrong so clean up */
|
||||
IUnknown* bufferParent;
|
||||
if (object->frontBuffer) {
|
||||
|
||||
IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
|
||||
IUnknown_Release(bufferParent); /* once for the get parent */
|
||||
if (IUnknown_Release(bufferParent) > 0) {
|
||||
FIXME("(%p) Something's still holding the front buffer\n",This);
|
||||
}
|
||||
}
|
||||
if (object->backBuffer) {
|
||||
int i;
|
||||
for(i = 0; i < object->presentParms.BackBufferCount; i++) {
|
||||
if(object->backBuffer[i]) {
|
||||
IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
|
||||
IUnknown_Release(bufferParent); /* once for the get parent */
|
||||
if (IUnknown_Release(bufferParent) > 0) {
|
||||
FIXME("(%p) Something's still holding the back buffer\n",This);
|
||||
}
|
||||
error:
|
||||
if (object->backBuffer) {
|
||||
int i;
|
||||
for(i = 0; i < object->presentParms.BackBufferCount; i++) {
|
||||
if(object->backBuffer[i]) {
|
||||
IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
|
||||
IUnknown_Release(bufferParent); /* once for the get parent */
|
||||
if (IUnknown_Release(bufferParent) > 0) {
|
||||
FIXME("(%p) Something's still holding the back buffer\n",This);
|
||||
}
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, object->backBuffer);
|
||||
object->backBuffer = NULL;
|
||||
}
|
||||
/* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
|
||||
/* Clean up the context */
|
||||
/* check that we are the current context first (we shouldn't be though!) */
|
||||
if (newCtx != 0) {
|
||||
if(glXGetCurrentContext() == newCtx) {
|
||||
glXMakeCurrent(object->display, None, NULL);
|
||||
}
|
||||
glXDestroyContext(object->display, newCtx);
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, object);
|
||||
HeapFree(GetProcessHeap(), 0, object->backBuffer);
|
||||
object->backBuffer = NULL;
|
||||
}
|
||||
|
||||
if(object->context) {
|
||||
DestroyContext(This, object->context);
|
||||
}
|
||||
if(object->frontBuffer) {
|
||||
IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
|
||||
IUnknown_Release(bufferParent); /* once for the get parent */
|
||||
if (IUnknown_Release(bufferParent) > 0) {
|
||||
FIXME("(%p) Something's still holding the front buffer\n",This);
|
||||
}
|
||||
}
|
||||
if(object) HeapFree(GetProcessHeap(), 0, object);
|
||||
return hr;
|
||||
}
|
||||
|
||||
@ -1985,13 +1829,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR
|
||||
* with Default values
|
||||
*/
|
||||
|
||||
((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->display);
|
||||
((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->context->display);
|
||||
/* Setup all the devices defaults */
|
||||
IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
|
||||
#if 0
|
||||
IWineD3DImpl_CheckGraphicsMemory();
|
||||
#endif
|
||||
LEAVE_GL();
|
||||
|
||||
/* Initialize our list of GLSL programs */
|
||||
list_init(&This->glsl_shader_progs);
|
||||
@ -2011,7 +1854,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR
|
||||
This->view_ident = 1;
|
||||
This->contexts[0]->last_was_rhw = 0;
|
||||
glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
|
||||
checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
|
||||
TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
|
||||
LEAVE_GL();
|
||||
|
||||
/* Clear the screen */
|
||||
IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
|
||||
@ -2765,7 +2610,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, D
|
||||
|
||||
/* If we have too many active lights, fail the call */
|
||||
if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
|
||||
FIXME("Program requests too many concurrent lights\n");
|
||||
FIXME("Program requests too many concurrent lights.\n");
|
||||
return WINED3DERR_INVALIDCALL;
|
||||
|
||||
/* If we have allocated all lights, but not all are enabled,
|
||||
|
@ -123,17 +123,8 @@ static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up the context */
|
||||
/* check that we are the current context first */
|
||||
if(glXGetCurrentContext() == This->context->glCtx){
|
||||
glXMakeCurrent(This->display, None, NULL);
|
||||
}
|
||||
glXDestroyContext(This->display, This->context->glCtx);
|
||||
DeleteContext(This->wineD3DDevice, This->context);
|
||||
/* IUnknown_Release(This->parent); This should only apply to the primary swapchain,
|
||||
all others are created by the caller, so releasing the parent should cause
|
||||
the child to be released, not the other way around!
|
||||
*/
|
||||
DestroyContext(This->wineD3DDevice, This->context);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
}
|
||||
|
||||
@ -184,125 +175,49 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO
|
||||
|
||||
if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
|
||||
/* TODO: If only source rect or dest rect are supplied then clip the window to match */
|
||||
TRACE("preseting display %p, drawable %ld\n", This->display, This->context->drawable);
|
||||
TRACE("preseting display %p, drawable %ld\n", This->context->display, This->context->drawable);
|
||||
|
||||
/* Don't call checkGLcall, as glGetError is not applicable here */
|
||||
if (hDestWindowOverride && This->win_handle != hDestWindowOverride) {
|
||||
/* Set this swapchain up to point to the new destination.. */
|
||||
HDC hDc;
|
||||
WINED3DLOCKED_RECT r;
|
||||
Display *display;
|
||||
BYTE *mem;
|
||||
|
||||
/* Ok, now we switch the opengl context behind the context manager's back. Tidy this up when
|
||||
* the ctx manager is completely in place
|
||||
TRACE("Performing dest override of swapchain %p from window %p to %p\n", This, This->win_handle, hDestWindowOverride);
|
||||
if(This->context == This->wineD3DDevice->contexts[0]) {
|
||||
/* The primary context 'owns' all the opengl resources. Destroying and recreating that context would require downloading
|
||||
* all opengl resources, deleting the gl resources, destroying all other contexts, then recreating all other contexts
|
||||
* and reload the resources
|
||||
*/
|
||||
/* FIXME: Never access */
|
||||
IWineD3DSwapChainImpl *swapChainImpl;
|
||||
IWineD3DDevice_GetSwapChain((IWineD3DDevice *)This->wineD3DDevice, 0 , (IWineD3DSwapChain **)&swapChainImpl);
|
||||
FIXME("Unable to render to a destination window %p\n", hDestWindowOverride );
|
||||
if(This == swapChainImpl){
|
||||
/* FIXME: this will be fixed by moving to a context management system */
|
||||
FIXME("Cannot change the target of the implicit swapchain\n");
|
||||
}else{
|
||||
HDC hDc;
|
||||
XVisualInfo template;
|
||||
int num;
|
||||
Display *oldDisplay = This->display;
|
||||
GLXContext oldContext = This->context->glCtx;
|
||||
IUnknown* tmp;
|
||||
GLXContext currentContext;
|
||||
Drawable currentDrawable;
|
||||
hDc = GetDC(hDestWindowOverride);
|
||||
This->win_handle = hDestWindowOverride;
|
||||
This->win = (Window)GetPropA( hDestWindowOverride, "__wine_x11_whole_window" );
|
||||
ERR("Cannot change the destination window of the owner of the primary context\n");
|
||||
} else {
|
||||
hDc = GetDC(hDestWindowOverride);
|
||||
This->win_handle = hDestWindowOverride;
|
||||
This->win = (Window)GetPropA( hDestWindowOverride, "__wine_x11_whole_window" );
|
||||
display = get_display(hDc);
|
||||
ReleaseDC(hDestWindowOverride, hDc);
|
||||
|
||||
TRACE("Creating a new context for the window %p\n", hDestWindowOverride);
|
||||
ENTER_GL();
|
||||
TRACE("Desctroying context %p %p\n", This->display, This->render_ctx);
|
||||
/* The old back buffer has to be copied over to the new back buffer. A lockrect - switchcontext - unlockrect
|
||||
* would suffice in theory, but it is rather nasty and may cause troubles with future changes of the locking code
|
||||
* So lock read only, copy the surface out, then lock with the discard flag and write back
|
||||
*/
|
||||
IWineD3DSurface_LockRect(This->backBuffer[0], &r, NULL, WINED3DLOCK_READONLY);
|
||||
mem = HeapAlloc(GetProcessHeap(), 0, r.Pitch * ((IWineD3DSurfaceImpl *) This->backBuffer[0])->currentDesc.Height);
|
||||
memcpy(mem, r.pBits, r.Pitch * ((IWineD3DSurfaceImpl *) This->backBuffer[0])->currentDesc.Height);
|
||||
IWineD3DSurface_UnlockRect(This->backBuffer[0]);
|
||||
|
||||
DestroyContext(This->wineD3DDevice, This->context);
|
||||
This->context = CreateContext(This->wineD3DDevice, (IWineD3DSurfaceImpl *) This->frontBuffer, display, This->win);
|
||||
|
||||
|
||||
LEAVE_GL();
|
||||
ENTER_GL();
|
||||
|
||||
This->display = get_display(hDc);
|
||||
TRACE("Got display%p for %p %p\n", This->display, hDc, hDestWindowOverride);
|
||||
ReleaseDC(hDestWindowOverride, hDc);
|
||||
template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
|
||||
This->visInfo = XGetVisualInfo(This->display, VisualIDMask, &template, &num);
|
||||
if (NULL == This->visInfo) {
|
||||
ERR("cannot really get XVisual\n");
|
||||
LEAVE_GL();
|
||||
return WINED3DERR_NOTAVAILABLE;
|
||||
}
|
||||
/* Now we have problems? well not really we just need to know what the implicit context is */
|
||||
/* now destroy the old context and create a new one (we should really copy the buffers over, and do the whole make current thing! */
|
||||
/* destroy the active context?*/
|
||||
TRACE("Creating new context for %p %p %p\n",This->display, This->visInfo, swapChainImpl->context->glCtx);
|
||||
This->context->glCtx = glXCreateContext(This->display, This->visInfo, swapChainImpl->context->glCtx, GL_TRUE);
|
||||
|
||||
if (NULL == This->context->glCtx) {
|
||||
ERR("cannot create glxContext\n");
|
||||
}
|
||||
This->context->drawable = This->win;
|
||||
This->render_ctx = This->context->glCtx;
|
||||
/* Setup some default states TODO: apply the stateblock to the new context */
|
||||
/** save current context and drawable **/
|
||||
currentContext = glXGetCurrentContext();
|
||||
currentDrawable = glXGetCurrentDrawable();
|
||||
|
||||
if (glXMakeCurrent(This->display, This->win, This->context->glCtx) == False) {
|
||||
ERR("Error in setting current context (display %p context %p drawable %ld)!\n", This->display, This->context->glCtx, This->win);
|
||||
}
|
||||
|
||||
checkGLcall("glXMakeCurrent");
|
||||
|
||||
/* Clear the screen */
|
||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
checkGLcall("glClearColor");
|
||||
glClearIndex(0);
|
||||
glClearDepth(1);
|
||||
glClearStencil(0);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
checkGLcall("glClear");
|
||||
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
checkGLcall("glColor3f");
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
checkGLcall("glEnable");
|
||||
|
||||
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
|
||||
checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
|
||||
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
|
||||
checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
|
||||
|
||||
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
|
||||
checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
|
||||
|
||||
/* If this swapchain is currently the active context then make this swapchain active */
|
||||
if(IWineD3DSurface_GetContainer(This->wineD3DDevice->render_targets[0], &IID_IWineD3DSwapChain, (void **)&tmp) == WINED3D_OK){
|
||||
if(tmp != (IUnknown *)This){
|
||||
glXMakeCurrent(This->display, currentDrawable, currentContext);
|
||||
checkGLcall("glXMakeCurrent");
|
||||
}
|
||||
IUnknown_Release(tmp);
|
||||
}else{
|
||||
/* reset the context */
|
||||
glXMakeCurrent(This->display, currentDrawable, currentContext);
|
||||
checkGLcall("glXMakeCurrent");
|
||||
}
|
||||
/* delete the old contxt*/
|
||||
glXDestroyContext(oldDisplay, oldContext); /* Should this happen on an active context? seems a bad idea */
|
||||
LEAVE_GL();
|
||||
}
|
||||
IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapChainImpl);
|
||||
|
||||
IWineD3DSurface_LockRect(This->backBuffer[0], &r, NULL, WINED3DLOCK_DISCARD);
|
||||
memcpy(r.pBits, mem, r.Pitch * ((IWineD3DSurfaceImpl *) This->backBuffer[0])->currentDesc.Height);
|
||||
HeapFree(GetProcessHeap(), 0, mem);
|
||||
IWineD3DSurface_UnlockRect(This->backBuffer[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* TODO: The slow way, save the data to memory, create a new context for the destination window, transfer the data cleanup, it may be a good idea to the move this swapchain over to the using the target winows context so that it runs faster in feature. */
|
||||
|
||||
glXSwapBuffers(This->display, This->context->drawable); /* TODO: cycle through the swapchain buffers */
|
||||
glXSwapBuffers(This->context->display, This->context->drawable); /* TODO: cycle through the swapchain buffers */
|
||||
|
||||
TRACE("glXSwapBuffers called, Starting new frame\n");
|
||||
/* FPS support */
|
||||
|
@ -482,6 +482,8 @@ struct WineD3DContext {
|
||||
/* The actual opengl context */
|
||||
GLXContext glCtx;
|
||||
Drawable drawable;
|
||||
Display *display;
|
||||
BOOL isPBuffer;
|
||||
};
|
||||
|
||||
typedef enum ContextUsage {
|
||||
@ -491,9 +493,7 @@ typedef enum ContextUsage {
|
||||
} ContextUsage;
|
||||
|
||||
void ActivateContext(IWineD3DDeviceImpl *device, IWineD3DSurface *target, ContextUsage usage);
|
||||
WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, Window win);
|
||||
WineD3DContext *AddContext(IWineD3DDeviceImpl *This, GLXContext glCtx, Drawable drawable);
|
||||
void DeleteContext(IWineD3DDeviceImpl *This, WineD3DContext *context);
|
||||
WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, Display *display, Window win);
|
||||
void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context);
|
||||
void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target);
|
||||
|
||||
@ -1335,11 +1335,6 @@ typedef struct IWineD3DSwapChainImpl
|
||||
|
||||
HWND win_handle;
|
||||
Window win;
|
||||
Display *display;
|
||||
|
||||
XVisualInfo *visInfo;
|
||||
GLXContext render_ctx;
|
||||
/* This has been left in device for now, but needs moving off into a rendertarget management class and separated out from swapchains and devices. */
|
||||
} IWineD3DSwapChainImpl;
|
||||
|
||||
extern const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl;
|
||||
|
Loading…
x
Reference in New Issue
Block a user