COM_INTERFACE(IGalliumDXGIBackend, IUnknown)
+// TODO: somehow check whether the window is fully obscured or not
struct GalliumDXGIIdentityBackend : public GalliumComObject<IGalliumDXGIBackend>
{
- virtual void * STDMETHODCALLTYPE BeginPresent(
+ virtual HRESULT STDMETHODCALLTYPE BeginPresent(
HWND hwnd,
+ void** present_cookie,
void** window,
RECT *rect,
RGNDATA **rgndata,
// yes, because we like things looking good
*preserve_aspect_ratio = TRUE;
- return 0;
+ *present_cookie = 0;
+ return S_OK;
}
virtual void STDMETHODCALLTYPE EndPresent(
void* present_cookie
)
{}
+
+ virtual HRESULT STDMETHODCALLTYPE TestPresent(HWND hwnd)
+ {
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetPresentSize(
+ HWND hwnd,
+ unsigned* width,
+ unsigned* height
+ )
+ {
+ *width = 0;
+ *height = 0;
+ return S_OK;
+ }
+};
+
+// TODO: maybe install an X11 error hook, so we can return errors properly
+struct GalliumDXGIX11IdentityBackend : public GalliumDXGIIdentityBackend
+{
+ Display* dpy;
+
+ GalliumDXGIX11IdentityBackend(Display* dpy)
+ : dpy(dpy)
+ {}
+
+ virtual HRESULT STDMETHODCALLTYPE GetPresentSize(
+ HWND hwnd,
+ unsigned* width,
+ unsigned* height
+ )
+ {
+ XWindowAttributes xwa;
+ XGetWindowAttributes(dpy, (Window)hwnd, &xwa);
+ *width = xwa.width;
+ *height = xwa.height;
+ return S_OK;
+ }
};
struct GalliumDXGIFactory : public GalliumDXGIObject<IDXGIFactory1, IUnknown>
{
if(p_backend)
backend = p_backend;
+ else if(!strcmp(platform->name, "X11"))
+ backend.reset(new GalliumDXGIX11IdentityBackend((Display*)display));
else
backend.reset(new GalliumDXGIIdentityBackend());
}
blitter.reset(new dxgi_blitter(pipe));
window = 0;
+
+ hr = resolve_zero_width_height(true);
+ if(!SUCCEEDED(hr))
+ throw hr;
}
void init_for_window()
{
XWindowAttributes xwa;
XGetWindowAttributes((Display*)parent->display, (Window)window, &xwa);
+ assert(adapter->configs_by_native_visual_id.count(xwa.visual->visualid));
config_num = adapter->configs_by_native_visual_id[xwa.visual->visualid];
}
else
return true;
}
+ HRESULT resolve_zero_width_height(bool force = false)
+ {
+ if(!force && desc.BufferDesc.Width && desc.BufferDesc.Height)
+ return S_OK;
+
+ unsigned width, height;
+ HRESULT hr = parent->backend->GetPresentSize(desc.OutputWindow, &width, &height);
+ if(!SUCCEEDED(hr))
+ return hr;
+
+ // On Windows, 8 is used, and a debug message saying so gets printed
+ if(!width)
+ width = 8;
+ if(!height)
+ height = 8;
+
+ if(!desc.BufferDesc.Width)
+ desc.BufferDesc.Width = width;
+ if(!desc.BufferDesc.Height)
+ desc.BufferDesc.Height = height;
+ return S_OK;
+ }
+
virtual HRESULT STDMETHODCALLTYPE Present(
UINT sync_interval,
UINT flags)
{
+ HRESULT hr;
if(flags & DXGI_PRESENT_TEST)
- return S_OK;
+ return parent->backend->TestPresent(desc.OutputWindow);
if(!buffer0)
{
struct pipe_resource* dst;
struct pipe_resource* src;
struct pipe_surface* dst_surface;
+ enum native_attachment att;
+
+ void* present_cookie;
+ hr = parent->backend->BeginPresent(desc.OutputWindow, &present_cookie, &cur_window, &rect, &rgndata, &preserve_aspect_ratio);
+ if(hr != S_OK)
+ return hr;
- void* present_cookie = parent->backend->BeginPresent(desc.OutputWindow, &cur_window, &rect, &rgndata, &preserve_aspect_ratio);
if(!cur_window || rect.left >= rect.right || rect.top >= rect.bottom)
goto end_present;
return DXGI_ERROR_DEVICE_REMOVED;
}
- db = !!(config->buffer_mask & NATIVE_ATTACHMENT_BACK_LEFT);
+ db = !!(config->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT));
dst = resources[db ? NATIVE_ATTACHMENT_BACK_LEFT : NATIVE_ATTACHMENT_FRONT_LEFT];
src = gallium_buffer0;
dst_surface = 0;
+ assert(src);
+ assert(dst);
+
/* TODO: sharing the context for blitting won't work correctly if queries are active
* Hopefully no one is crazy enough to keep queries active while presenting, expecting
* sensible results.
unsigned blit_x, blit_y, blit_w, blit_h;
float black[4] = {0, 0, 0, 0};
- if(!formats_compatible || src->width0 != dst_w || src->height0 != dst_h)
- dst_surface = pipe->screen->get_tex_surface(pipe->screen, dst, 0, 0, 0, PIPE_BIND_RENDER_TARGET);
+ if(!formats_compatible || src->width0 != dst_w || src->height0 != dst_h) {
+ struct pipe_surface templat;
+ templat.usage = PIPE_BIND_RENDER_TARGET;
+ templat.format = dst->format;
+ templat.u.tex.level = 0;
+ templat.u.tex.first_layer = 0;
+ templat.u.tex.last_layer = 0;
+ dst_surface = pipe->create_surface(pipe, dst, &templat);
+ }
if(preserve_aspect_ratio)
{
if(formats_compatible && blit_w == src->width0 && blit_h == src->height0)
{
- pipe_subresource sr;
- sr.face = 0;
- sr.level = 0;
- pipe->resource_copy_region(pipe, dst, sr, rect.left, rect.top, 0, src, sr, 0, 0, 0, blit_w, blit_h);
+ pipe_box box;
+ box.x = box.y = box.z;
+ box.width = blit_w;
+ box.height = blit_h;
+ box.z = 1;
+ pipe->resource_copy_region(pipe, dst, 0, rect.left, rect.top, 0, src, 0, &box);
}
else
{
}
if(dst_surface)
- pipe->screen->tex_surface_destroy(dst_surface);
+ pipe->surface_destroy(pipe, dst_surface);
- if(db)
- {
- if(!surface->swap_buffers(surface))
- return DXGI_ERROR_DEVICE_REMOVED;
- }
- else
- {
- if(!surface->flush_frontbuffer(surface))
- return DXGI_ERROR_DEVICE_REMOVED;
- }
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, 0);
+
+ att = (db) ? NATIVE_ATTACHMENT_BACK_LEFT : NATIVE_ATTACHMENT_FRONT_LEFT;
+ if(!surface->present(surface, att, FALSE, 0))
+ return DXGI_ERROR_DEVICE_REMOVED;
end_present:
parent->backend->EndPresent(desc.OutputWindow, present_cookie);
desc.BufferDesc.Width = width;
desc.BufferDesc.Height = height;
desc.Flags = swap_chain_flags;
- return S_OK;
+ return resolve_zero_width_height();
}
virtual HRESULT STDMETHODCALLTYPE ResizeTarget(