gallium: add usage parameter to pipe_buffer_create
[mesa.git] / src / gallium / state_trackers / d3d1x / dxgi / src / dxgi_native.cpp
index 99d80eae319832ce27e93c87a59e42a48048b8ae..2e45f3f43e97be64ae08a34cc4309bbd416209d4 100644 (file)
@@ -65,10 +65,12 @@ struct GalliumDXGIObject : public GalliumPrivateDataComObject<Base>
 
 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,
@@ -84,7 +86,8 @@ struct GalliumDXGIIdentityBackend : public GalliumComObject<IGalliumDXGIBackend>
 
                // yes, because we like things looking good
                *preserve_aspect_ratio = TRUE;
-               return 0;
+               *present_cookie = 0;
+               return S_OK;
        }
 
        virtual void STDMETHODCALLTYPE EndPresent(
@@ -92,6 +95,45 @@ struct GalliumDXGIIdentityBackend : public GalliumComObject<IGalliumDXGIBackend>
                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>
@@ -107,6 +149,8 @@ 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());
        }
@@ -212,11 +256,16 @@ struct GalliumDXGIAdapter
        {
                this->parent = factory;
 
+                /* FIXME handler should be static */
                handler.invalid_surface = handle_invalid_surface;
                handler.new_drm_screen = dxgi_loader_create_drm_screen;
                handler.new_sw_screen = dxgi_loader_create_sw_screen;
-               display = platform->create_display(dpy, &handler, this);
+               platform->set_event_handler(&handler);
+
+               display = platform->create_display(dpy, FALSE, this);
                if(!display)
+                   display = platform->create_display(dpy, TRUE, this);
+                if(!display)
                        throw E_FAIL;
                memset(&desc, 0, sizeof(desc));
                std::string s = std::string("GalliumD3D on ") + display->screen->get_name(display->screen) + " by " + display->screen->get_vendor(display->screen);
@@ -745,9 +794,9 @@ struct dxgi_blitter
                const unsigned semantic_indices[] = { 0, 0 };
                vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names, semantic_indices);
 
-               vbuf.buffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, sizeof(quad_data));
+               vbuf.buffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER,
+                                                PIPE_USAGE_STREAM, sizeof(quad_data));
                vbuf.buffer_offset = 0;
-               vbuf.max_index = ~0;
                vbuf.stride = 4 * sizeof(float);
                pipe_buffer_write(pipe, vbuf.buffer, 0, sizeof(quad_data), quad_data);
 
@@ -887,6 +936,10 @@ struct GalliumDXGISwapChain : public GalliumDXGIObject<IDXGISwapChain, GalliumDX
 
                blitter.reset(new dxgi_blitter(pipe));
                window = 0;
+
+               hr = resolve_zero_width_height(true);
+               if(!SUCCEEDED(hr))
+                       throw hr;
        }
 
        void init_for_window()
@@ -902,6 +955,7 @@ struct GalliumDXGISwapChain : public GalliumDXGIObject<IDXGISwapChain, GalliumDX
                {
                        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
@@ -1005,12 +1059,36 @@ struct GalliumDXGISwapChain : public GalliumDXGIObject<IDXGISwapChain, GalliumDX
                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)
                {
@@ -1028,8 +1106,13 @@ struct GalliumDXGISwapChain : public GalliumDXGIObject<IDXGISwapChain, GalliumDX
                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;
 
@@ -1045,11 +1128,14 @@ struct GalliumDXGISwapChain : public GalliumDXGIObject<IDXGISwapChain, GalliumDX
                                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.
@@ -1078,8 +1164,15 @@ struct GalliumDXGISwapChain : public GalliumDXGIObject<IDXGISwapChain, GalliumDX
                        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)
                        {
@@ -1118,10 +1211,12 @@ struct GalliumDXGISwapChain : public GalliumDXGIObject<IDXGISwapChain, GalliumDX
 
                        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
                        {
@@ -1137,20 +1232,13 @@ struct GalliumDXGISwapChain : public GalliumDXGIObject<IDXGISwapChain, GalliumDX
                }
 
                if(dst_surface)
-                       pipe->screen->tex_surface_destroy(dst_surface);
+                       pipe->surface_destroy(pipe, dst_surface);
 
-               pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME);
+               pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, 0);
 
-               if(db)
-               {
-                       if(!surface->swap_buffers(surface))
-                               return DXGI_ERROR_DEVICE_REMOVED;
-               }
-               else
-               {
-                       if(!surface->flush_frontbuffer(surface))
-                               return DXGI_ERROR_DEVICE_REMOVED;
-               }
+               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);
@@ -1234,7 +1322,7 @@ end_present:
                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(