gallium: Learn about kopper

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14541>
This commit is contained in:
Adam Jackson 2022-03-15 15:36:28 -04:00 committed by Marge Bot
parent bab8d97ea9
commit d760a9151b
20 changed files with 894 additions and 29 deletions

View File

@ -667,6 +667,32 @@ trace_screen_resource_create(struct pipe_screen *_screen,
return result;
}
static struct pipe_resource *
trace_screen_resource_create_drawable(struct pipe_screen *_screen,
const struct pipe_resource *templat,
const void *loader_data)
{
struct trace_screen *tr_scr = trace_screen(_screen);
struct pipe_screen *screen = tr_scr->screen;
struct pipe_resource *result;
trace_dump_call_begin("pipe_screen", "resource_create_drawable");
trace_dump_arg(ptr, screen);
trace_dump_arg(resource_template, templat);
trace_dump_arg(ptr, loader_data);
result = screen->resource_create_drawable(screen, templat, loader_data);
trace_dump_ret(ptr, result);
trace_dump_call_end();
if (result)
result->screen = _screen;
return result;
}
static struct pipe_resource *
trace_screen_resource_create_with_modifiers(struct pipe_screen *_screen, const struct pipe_resource *templat,
const uint64_t *modifiers, int modifiers_count)
@ -1283,6 +1309,7 @@ trace_screen_create(struct pipe_screen *screen)
tr_scr->base.resource_create = trace_screen_resource_create;
SCR_INIT(resource_create_with_modifiers);
tr_scr->base.resource_create_unbacked = trace_screen_resource_create_unbacked;
SCR_INIT(resource_create_drawable);
tr_scr->base.resource_bind_backing = trace_screen_resource_bind_backing;
tr_scr->base.resource_from_handle = trace_screen_resource_from_handle;
tr_scr->base.allocate_memory = trace_screen_allocate_memory;
@ -1345,3 +1372,12 @@ trace_screen(struct pipe_screen *screen)
assert(screen->destroy == trace_screen_destroy);
return (struct trace_screen *)screen;
}
struct pipe_screen *
trace_screen_unwrap(struct pipe_screen *_screen)
{
if (_screen->destroy != trace_screen_destroy)
return _screen;
struct trace_screen *tr_scr = trace_screen(_screen);
return tr_scr->screen;
}

View File

@ -59,6 +59,8 @@ struct trace_screen
struct trace_screen *
trace_screen(struct pipe_screen *screen);
struct pipe_screen *
trace_screen_unwrap(struct pipe_screen *_screen);
#ifdef __cplusplus
}

View File

@ -45,7 +45,7 @@ libpipe_loader_static = static_library(
files_pipe_loader,
include_directories : [
inc_util, inc_loader, inc_gallium, inc_include, inc_src, inc_gallium_aux,
inc_gallium_winsys,
inc_gallium_winsys, inc_gallium_drivers,
],
c_args : [libpipe_loader_defines, '-DGALLIUM_STATIC_TARGETS=1'],
gnu_symbol_visibility : 'hidden',
@ -59,7 +59,7 @@ libpipe_loader_dynamic = static_library(
files_pipe_loader,
include_directories : [
inc_util, inc_loader, inc_gallium, inc_include, inc_src, inc_gallium_aux,
inc_gallium_winsys,
inc_gallium_winsys, inc_gallium_drivers,
],
c_args : [
libpipe_loader_defines,

View File

@ -143,6 +143,20 @@ bool
pipe_loader_sw_probe_dri(struct pipe_loader_device **devs,
const struct drisw_loader_funcs *drisw_lf);
/**
* Initialize vk dri device give the drisw_loader_funcs.
*
* This function is platform-specific.
*
* Function does not take ownership of the fd, but duplicates it locally.
* The local fd is closed during pipe_loader_release.
*
* \sa pipe_loader_probe
*/
bool
pipe_loader_vk_probe_dri(struct pipe_loader_device **devs,
const struct drisw_loader_funcs *drisw_lf);
/**
* Initialize a kms backed sw device given an fd.
*

View File

@ -43,7 +43,7 @@
#include "frontend/drisw_api.h"
#include "frontend/sw_driver.h"
#include "frontend/sw_winsys.h"
#include "util/driconf.h"
struct pipe_loader_sw_device {
struct pipe_loader_device base;
@ -58,6 +58,9 @@ struct pipe_loader_sw_device {
#define pipe_loader_sw_device(dev) ((struct pipe_loader_sw_device *)dev)
static const struct pipe_loader_ops pipe_loader_sw_ops;
#ifdef HAVE_ZINK
static const struct pipe_loader_ops pipe_loader_vk_ops;
#endif
#ifdef GALLIUM_STATIC_TARGETS
static const struct sw_driver_descriptor driver_descriptors = {
@ -90,6 +93,37 @@ static const struct sw_driver_descriptor driver_descriptors = {
};
#endif
#if defined(GALLIUM_STATIC_TARGETS) && defined(HAVE_ZINK)
static const struct sw_driver_descriptor kopper_driver_descriptors = {
.create_screen = sw_screen_create_zink,
.winsys = {
#ifdef HAVE_PIPE_LOADER_DRI
{
.name = "dri",
.create_winsys = dri_create_sw_winsys,
},
#endif
#ifdef HAVE_PIPE_LOADER_KMS
{
.name = "kms_dri",
.create_winsys = kms_dri_create_winsys,
},
#endif
#ifndef __ANDROID__
{
.name = "null",
.create_winsys = null_sw_create,
},
{
.name = "wrapped",
.create_winsys = wrapper_sw_winsys_wrap_pipe_screen,
},
#endif
{ 0 },
}
};
#endif
static bool
pipe_loader_sw_probe_init_common(struct pipe_loader_sw_device *sdev)
{
@ -124,6 +158,42 @@ pipe_loader_sw_probe_init_common(struct pipe_loader_sw_device *sdev)
return true;
}
#ifdef HAVE_ZINK
static bool
pipe_loader_vk_probe_init_common(struct pipe_loader_sw_device *sdev)
{
sdev->base.type = PIPE_LOADER_DEVICE_PLATFORM;
sdev->base.driver_name = "kopper";
sdev->base.ops = &pipe_loader_vk_ops;
sdev->fd = -1;
#ifdef GALLIUM_STATIC_TARGETS
sdev->dd = &kopper_driver_descriptors;
if (!sdev->dd)
return false;
#else
const char *search_dir = getenv("GALLIUM_PIPE_SEARCH_DIR");
if (search_dir == NULL)
search_dir = PIPE_SEARCH_DIR;
sdev->lib = pipe_loader_find_module("swrast", search_dir);
if (!sdev->lib)
return false;
sdev->dd = (const struct sw_driver_descriptor *)
util_dl_get_proc_address(sdev->lib, "swrast_driver_descriptor");
if (!sdev->dd){
util_dl_close(sdev->lib);
sdev->lib = NULL;
return false;
}
#endif
return true;
}
#endif
static void
pipe_loader_sw_probe_teardown_common(struct pipe_loader_sw_device *sdev)
{
@ -163,6 +233,37 @@ fail:
FREE(sdev);
return false;
}
#ifdef HAVE_ZINK
bool
pipe_loader_vk_probe_dri(struct pipe_loader_device **devs, const struct drisw_loader_funcs *drisw_lf)
{
struct pipe_loader_sw_device *sdev = CALLOC_STRUCT(pipe_loader_sw_device);
int i;
if (!sdev)
return false;
if (!pipe_loader_vk_probe_init_common(sdev))
goto fail;
for (i = 0; sdev->dd->winsys[i].name; i++) {
if (strcmp(sdev->dd->winsys[i].name, "dri") == 0) {
sdev->ws = sdev->dd->winsys[i].create_winsys(drisw_lf);
break;
}
}
if (!sdev->ws)
goto fail;
*devs = &sdev->base;
return true;
fail:
pipe_loader_sw_probe_teardown_common(sdev);
FREE(sdev);
return false;
}
#endif
#endif
#ifdef HAVE_PIPE_LOADER_KMS
@ -303,6 +404,19 @@ pipe_loader_sw_get_driconf(struct pipe_loader_device *dev, unsigned *count)
return NULL;
}
#ifdef HAVE_ZINK
static const driOptionDescription zink_driconf[] = {
#include "zink/driinfo_zink.h"
};
static const struct driOptionDescription *
pipe_loader_vk_get_driconf(struct pipe_loader_device *dev, unsigned *count)
{
*count = ARRAY_SIZE(zink_driconf);
return zink_driconf;
}
#endif
static struct pipe_screen *
pipe_loader_sw_create_screen(struct pipe_loader_device *dev,
const struct pipe_screen_config *config, bool sw_vk)
@ -310,7 +424,7 @@ pipe_loader_sw_create_screen(struct pipe_loader_device *dev,
struct pipe_loader_sw_device *sdev = pipe_loader_sw_device(dev);
struct pipe_screen *screen;
screen = sdev->dd->create_screen(sdev->ws, sw_vk);
screen = sdev->dd->create_screen(sdev->ws, config, sw_vk);
if (!screen)
sdev->ws->destroy(sdev->ws);
@ -322,3 +436,11 @@ static const struct pipe_loader_ops pipe_loader_sw_ops = {
.get_driconf = pipe_loader_sw_get_driconf,
.release = pipe_loader_sw_release
};
#ifdef HAVE_ZINK
static const struct pipe_loader_ops pipe_loader_vk_ops = {
.create_screen = pipe_loader_sw_create_screen,
.get_driconf = pipe_loader_vk_get_driconf,
.release = pipe_loader_sw_release
};
#endif

View File

@ -3,6 +3,7 @@
#define INLINE_SW_HELPER_H
#include "pipe/p_compiler.h"
#include "pipe/p_screen.h"
#include "util/u_debug.h"
#include "util/debug.h"
#include "frontend/sw_winsys.h"
@ -92,9 +93,6 @@ sw_screen_create_vk(struct sw_winsys *winsys, bool sw_vk)
#endif
#if defined(GALLIUM_SOFTPIPE)
(sw_vk ? "" : "softpipe"),
#endif
#if defined(GALLIUM_ZINK)
(sw_vk || only_sw) ? "" : "zink",
#endif
};
@ -109,6 +107,16 @@ sw_screen_create_vk(struct sw_winsys *winsys, bool sw_vk)
return NULL;
}
static inline struct pipe_screen *
sw_screen_create_zink(struct sw_winsys *winsys, const struct pipe_screen_config *config, bool whatever)
{
#if defined(GALLIUM_ZINK)
return zink_create_screen(winsys, config);
#else
return NULL;
#endif
}
static inline struct pipe_screen *
sw_screen_create(struct sw_winsys *winsys)
{

View File

@ -39,7 +39,7 @@
#endif
static inline struct pipe_screen *
sw_screen_create_named(struct sw_winsys *winsys, const char *driver)
sw_screen_create_named(struct sw_winsys *winsys, const struct pipe_screen_config *config, const char *driver)
{
struct pipe_screen *screen = NULL;
@ -80,7 +80,7 @@ sw_screen_create_named(struct sw_winsys *winsys, const char *driver)
}
struct pipe_screen *
sw_screen_create_vk(struct sw_winsys *winsys, bool sw_vk)
sw_screen_create_vk(struct sw_winsys *winsys, const struct pipe_screen_config *config, bool sw_vk)
{
UNUSED bool only_sw = env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
const char *drivers[] = {
@ -96,14 +96,11 @@ sw_screen_create_vk(struct sw_winsys *winsys, bool sw_vk)
#endif
#if defined(GALLIUM_SOFTPIPE)
sw_vk ? "" : "softpipe",
#endif
#if defined(GALLIUM_ZINK)
(sw_vk || only_sw) ? "" : "zink",
#endif
};
for (unsigned i = 0; i < ARRAY_SIZE(drivers); i++) {
struct pipe_screen *screen = sw_screen_create_named(winsys, drivers[i]);
struct pipe_screen *screen = sw_screen_create_named(winsys, config, drivers[i]);
if (screen)
return screen;
/* If the env var is set, don't keep trying things */
@ -113,9 +110,19 @@ sw_screen_create_vk(struct sw_winsys *winsys, bool sw_vk)
return NULL;
}
struct pipe_screen *
sw_screen_create_zink(struct sw_winsys *winsys, const struct pipe_screen_config *config, bool whatever)
{
#if defined(GALLIUM_ZINK)
return zink_create_screen(winsys);
#else
return NULL;
#endif
}
struct pipe_screen *
sw_screen_create(struct sw_winsys *winsys)
{
return sw_screen_create_vk(winsys, false);
return sw_screen_create_vk(winsys, NULL, false);
}
#endif

View File

@ -5,7 +5,9 @@ struct pipe_screen;
struct sw_winsys;
struct pipe_screen *
sw_screen_create_vk(struct sw_winsys *winsys, bool sw_vk);
sw_screen_create_vk(struct sw_winsys *winsys, const struct pipe_screen_config *config, bool sw_vk);
struct pipe_screen *
sw_screen_create_zink(struct sw_winsys *winsys, const struct pipe_screen_config *config, bool whatever);
struct pipe_screen *
sw_screen_create(struct sw_winsys *winsys);

View File

@ -209,7 +209,12 @@ dri2_drawable_get_buffers(struct dri_drawable *drawable,
return buffers;
}
static bool
bool
dri_image_drawable_get_buffers(struct dri_drawable *drawable,
struct __DRIimageList *images,
const enum st_attachment_type *statts,
unsigned statts_count);
bool
dri_image_drawable_get_buffers(struct dri_drawable *drawable,
struct __DRIimageList *images,
const enum st_attachment_type *statts,
@ -1864,6 +1869,36 @@ static const __DRIimageExtension dri2ImageExtensionTempl = {
.createImageWithModifiers2 = NULL,
};
const __DRIimageExtension driVkImageExtension = {
.base = { __DRI_IMAGE, 20 },
.createImageFromName = dri2_create_image_from_name,
.createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,
.destroyImage = dri2_destroy_image,
.createImage = dri2_create_image,
.queryImage = dri2_query_image,
.dupImage = dri2_dup_image,
.validateUsage = dri2_validate_usage,
.createImageFromNames = dri2_from_names,
.fromPlanar = dri2_from_planar,
.createImageFromTexture = dri2_create_from_texture,
.createImageFromFds = dri2_from_fds,
.createImageFromFds2 = dri2_from_fds2,
.createImageFromDmaBufs = dri2_from_dma_bufs,
.blitImage = dri2_blit_image,
.getCapabilities = dri2_get_capabilities,
.mapImage = dri2_map_image,
.unmapImage = dri2_unmap_image,
.createImageWithModifiers = dri2_create_image_with_modifiers,
.createImageFromDmaBufs2 = dri2_from_dma_bufs2,
.createImageFromDmaBufs3 = dri2_from_dma_bufs3,
.queryDmaBufFormats = dri2_query_dma_buf_formats,
.queryDmaBufModifiers = dri2_query_dma_buf_modifiers,
.queryDmaBufFormatModifierAttribs = dri2_query_dma_buf_format_modifier_attribs,
.createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2,
.createImageWithModifiers2 = dri2_create_image_with_modifiers2,
};
static const __DRIrobustnessExtension dri2Robustness = {
.base = { __DRI2_ROBUSTNESS, 1 }
};

View File

@ -41,6 +41,7 @@
#include "frontend/opencl_interop.h"
#include "os/os_thread.h"
#include "postprocess/filters.h"
#include "kopper_interface.h"
struct dri_context;
struct dri_drawable;
@ -106,6 +107,12 @@ dri_screen(__DRIscreen * sPriv)
return (struct dri_screen *)sPriv->driverPrivate;
}
static inline const __DRIkopperLoaderExtension *
dri_screen_get_kopper(struct dri_screen *screen)
{
return screen->sPriv->kopper_loader;
}
struct __DRIimageRec {
struct pipe_resource *texture;
unsigned level;
@ -167,6 +174,8 @@ extern const struct __DriverAPIRec galliumdrm_driver_api;
extern const __DRIextension *galliumdrm_driver_extensions[];
extern const struct __DriverAPIRec galliumsw_driver_api;
extern const __DRIextension *galliumsw_driver_extensions[];
extern const struct __DriverAPIRec galliumvk_driver_api;
extern const __DRIextension *galliumvk_driver_extensions[];
extern const __DRIconfigOptionsExtension gallium_config_options;
#endif

View File

@ -88,6 +88,8 @@ setupLoaderExtensions(__DRIscreen *psp,
psp->image.loader = (__DRIimageLoaderExtension *) extensions[i];
if (strcmp(extensions[i]->name, __DRI_MUTABLE_RENDER_BUFFER_LOADER) == 0)
psp->mutableRenderBuffer.loader = (__DRImutableRenderBufferLoaderExtension *) extensions[i];
if (strcmp(extensions[i]->name, __DRI_KOPPER_LOADER) == 0)
psp->kopper_loader = (__DRIkopperLoaderExtension *) extensions[i];
}
}

View File

@ -55,6 +55,7 @@
#include <GL/gl.h>
#include <GL/internal/dri_interface.h>
#include "kopper_interface.h"
#include "main/menums.h"
#include "main/formats.h"
#include "util/xmlconfig.h"
@ -185,6 +186,7 @@ struct __DRIscreenRec {
const __DRIextension **extensions;
const __DRIswrastLoaderExtension *swrast_loader;
const __DRIkopperLoaderExtension *kopper_loader;
struct {
/* Flag to indicate that this is a DRI2 screen. Many of the above

View File

@ -397,9 +397,15 @@ drisw_allocate_textures(struct dri_context *stctx,
templ.nr_samples = 0;
templ.nr_storage_samples = 0;
if (statts[i] == ST_ATTACHMENT_FRONT_LEFT &&
screen->base.screen->resource_create_front &&
loader->base.version >= 3) {
if (bind & PIPE_BIND_DISPLAY_TARGET &&
screen->base.screen->resource_create_drawable) {
drawable->textures[statts[i]] =
screen->base.screen->resource_create_drawable(screen->base.screen,
&templ,
drawable->dPriv);
} else if (statts[i] == ST_ATTACHMENT_FRONT_LEFT &&
screen->base.screen->resource_create_front &&
loader->base.version >= 3) {
drawable->textures[statts[i]] =
screen->base.screen->resource_create_front(screen->base.screen, &templ, (const void *)drawable);
} else

View File

@ -0,0 +1,591 @@
/*
* Copyright 2020 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "util/format/u_format.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_box.h"
#include "pipe/p_context.h"
#include "pipe-loader/pipe_loader.h"
#include "state_tracker/st_context.h"
#include "os/os_process.h"
#include "zink/zink_public.h"
#include "zink/zink_instance.h"
#include "driver_trace/tr_screen.h"
#include "dri_screen.h"
#include "utils.h"
#include "dri_context.h"
#include "dri_drawable.h"
#include "dri_helpers.h"
#include "dri_query_renderer.h"
#include <vulkan/vulkan.h>
struct kopper_drawable {
struct dri_drawable base;
struct kopper_loader_info info;
};
struct kopper_screen {
struct dri_screen base;
struct pipe_screen *screen; //unwrapped
};
extern const __DRIimageExtension driVkImageExtension;
static void
kopper_flush_drawable(__DRIdrawable *dPriv)
{
dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1);
}
static inline void
kopper_invalidate_drawable(__DRIdrawable *dPriv)
{
struct dri_drawable *drawable = dri_drawable(dPriv);
drawable->texture_stamp = dPriv->lastStamp - 1;
p_atomic_inc(&drawable->base.stamp);
}
static const __DRI2flushExtension driVkFlushExtension = {
.base = { __DRI2_FLUSH, 4 },
.flush = kopper_flush_drawable,
.invalidate = kopper_invalidate_drawable,
.flush_with_flags = dri_flush,
};
static const __DRIrobustnessExtension dri2Robustness = {
.base = { __DRI2_ROBUSTNESS, 1 }
};
static const __DRIextension *drivk_screen_extensions[] = {
&driTexBufferExtension.base,
&dri2RendererQueryExtension.base,
&dri2ConfigQueryExtension.base,
&dri2FenceExtension.base,
&dri2Robustness.base,
&driVkImageExtension.base,
&dri2FlushControlExtension.base,
&driVkFlushExtension.base,
NULL
};
static const __DRIconfig **
kopper_init_screen(__DRIscreen * sPriv)
{
const __DRIconfig **configs;
struct dri_screen *screen;
struct kopper_screen *kscreen;
struct pipe_screen *pscreen = NULL;
assert(sPriv->kopper_loader);
kscreen = CALLOC_STRUCT(kopper_screen);
if (!kscreen)
return NULL;
screen = &kscreen->base;
screen->sPriv = sPriv;
screen->fd = sPriv->fd;
screen->can_share_buffer = true;
sPriv->driverPrivate = (void *)kscreen;
bool success;
if (screen->fd != -1)
success = pipe_loader_drm_probe_fd(&screen->dev, screen->fd);
else
success = pipe_loader_vk_probe_dri(&screen->dev, NULL);
if (success) {
pscreen = pipe_loader_create_screen(screen->dev);
dri_init_options(screen);
}
if (!pscreen)
goto fail;
kscreen->screen = trace_screen_unwrap(pscreen);
configs = dri_init_screen_helper(screen, pscreen);
if (!configs)
goto fail;
assert(pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY));
screen->has_reset_status_query = true;
screen->lookup_egl_image = dri2_lookup_egl_image;
sPriv->extensions = drivk_screen_extensions;
const __DRIimageLookupExtension *image = sPriv->dri2.image;
if (image &&
image->base.version >= 2 &&
image->validateEGLImage &&
image->lookupEGLImageValidated) {
screen->validate_egl_image = dri2_validate_egl_image;
screen->lookup_egl_image_validated = dri2_lookup_egl_image_validated;
}
return configs;
fail:
dri_destroy_screen_helper(screen);
if (screen->dev)
pipe_loader_release(&screen->dev, 1);
FREE(screen);
return NULL;
}
// copypasta alert
static inline void
drisw_present_texture(struct pipe_context *pipe, __DRIdrawable *dPriv,
struct pipe_resource *ptex, struct pipe_box *sub_box)
{
struct dri_drawable *drawable = dri_drawable(dPriv);
struct dri_screen *screen = dri_screen(drawable->sPriv);
screen->base.screen->flush_frontbuffer(screen->base.screen, pipe, ptex, 0, 0, drawable, sub_box);
}
extern bool
dri_image_drawable_get_buffers(struct dri_drawable *drawable,
struct __DRIimageList *images,
const enum st_attachment_type *statts,
unsigned statts_count);
static void
kopper_allocate_textures(struct dri_context *ctx,
struct dri_drawable *drawable,
const enum st_attachment_type *statts,
unsigned statts_count)
{
struct dri_screen *screen = dri_screen(drawable->sPriv);
struct pipe_resource templ;
unsigned width, height;
boolean resized;
unsigned i;
struct __DRIimageList images;
__DRIdrawable *dri_drawable = drawable->dPriv;
const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
struct kopper_drawable *cdraw = (struct kopper_drawable *)drawable;
width = drawable->dPriv->w;
height = drawable->dPriv->h;
resized = (drawable->old_w != width ||
drawable->old_h != height);
/* First get the buffers from the loader */
if (image) {
if (!dri_image_drawable_get_buffers(drawable, &images,
statts, statts_count))
return;
}
if (image) {
if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
struct pipe_resource **buf =
&drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
struct pipe_resource *texture = images.front->texture;
dri_drawable->w = texture->width0;
dri_drawable->h = texture->height0;
pipe_resource_reference(buf, texture);
}
if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
struct pipe_resource **buf =
&drawable->textures[ST_ATTACHMENT_BACK_LEFT];
struct pipe_resource *texture = images.back->texture;
dri_drawable->w = texture->width0;
dri_drawable->h = texture->height0;
pipe_resource_reference(buf, texture);
}
if (images.image_mask & __DRI_IMAGE_BUFFER_SHARED) {
struct pipe_resource **buf =
&drawable->textures[ST_ATTACHMENT_BACK_LEFT];
struct pipe_resource *texture = images.back->texture;
dri_drawable->w = texture->width0;
dri_drawable->h = texture->height0;
pipe_resource_reference(buf, texture);
ctx->is_shared_buffer_bound = true;
} else {
ctx->is_shared_buffer_bound = false;
}
} else {
/* remove outdated textures */
if (resized) {
for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
if (drawable->textures[i] && i < ST_ATTACHMENT_DEPTH_STENCIL) {
drawable->textures[i]->width0 = width;
drawable->textures[i]->height0 = height;
} else
pipe_resource_reference(&drawable->textures[i], NULL);
pipe_resource_reference(&drawable->msaa_textures[i], NULL);
}
}
}
memset(&templ, 0, sizeof(templ));
templ.target = screen->target;
templ.width0 = width;
templ.height0 = height;
templ.depth0 = 1;
templ.array_size = 1;
templ.last_level = 0;
bool is_window = cdraw->info.bos.sType != 0;
uint32_t attachments = 0;
for (i = 0; i < statts_count; i++)
attachments |= BITFIELD_BIT(statts[i]);
bool front_only = attachments & ST_ATTACHMENT_FRONT_LEFT_MASK && !(attachments & ST_ATTACHMENT_BACK_LEFT_MASK);
for (i = 0; i < statts_count; i++) {
enum pipe_format format;
unsigned bind;
dri_drawable_get_format(drawable, statts[i], &format, &bind);
/* the texture already exists or not requested */
if (!drawable->textures[statts[i]]) {
if (statts[i] == ST_ATTACHMENT_BACK_LEFT ||
(statts[i] == ST_ATTACHMENT_FRONT_LEFT && front_only))
bind |= PIPE_BIND_DISPLAY_TARGET;
if (format == PIPE_FORMAT_NONE)
continue;
templ.format = format;
templ.bind = bind;
templ.nr_samples = 0;
templ.nr_storage_samples = 0;
if (statts[i] < ST_ATTACHMENT_DEPTH_STENCIL && is_window) {
void *data;
if (statts[i] == ST_ATTACHMENT_BACK_LEFT || (statts[i] == ST_ATTACHMENT_FRONT_LEFT && front_only))
data = &cdraw->info;
else
data = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
assert(data);
drawable->textures[statts[i]] =
screen->base.screen->resource_create_drawable(screen->base.screen, &templ, data);
} else
drawable->textures[statts[i]] =
screen->base.screen->resource_create(screen->base.screen, &templ);
}
if (drawable->stvis.samples > 1 && !drawable->msaa_textures[statts[i]]) {
templ.bind = templ.bind &
~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED | PIPE_BIND_DISPLAY_TARGET);
templ.nr_samples = drawable->stvis.samples;
templ.nr_storage_samples = drawable->stvis.samples;
drawable->msaa_textures[statts[i]] =
screen->base.screen->resource_create(screen->base.screen, &templ);
dri_pipe_blit(ctx->st->pipe,
drawable->msaa_textures[statts[i]],
drawable->textures[statts[i]]);
}
}
drawable->old_w = width;
drawable->old_h = height;
}
static inline void
get_drawable_info(__DRIdrawable *dPriv, int *x, int *y, int *w, int *h)
{
__DRIscreen *sPriv = dPriv->driScreenPriv;
const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
if (loader)
loader->getDrawableInfo(dPriv,
x, y, w, h,
dPriv->loaderPrivate);
}
static void
kopper_update_drawable_info(struct dri_drawable *drawable)
{
__DRIdrawable *dPriv = drawable->dPriv;
__DRIscreen *sPriv = dPriv->driScreenPriv;
struct kopper_drawable *cdraw = (struct kopper_drawable *)drawable;
bool is_window = cdraw->info.bos.sType != 0;
int x, y;
struct kopper_screen *kscreen = (struct kopper_screen*)sPriv->driverPrivate;
struct pipe_screen *screen = kscreen->screen;
struct pipe_resource *ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT] ?
drawable->textures[ST_ATTACHMENT_BACK_LEFT] :
drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
#if 0
if (is_window && ptex && kscreen->base.fd == -1)
zink_kopper_update(screen, ptex, &dPriv->w, &dPriv->h);
else
#endif
get_drawable_info(dPriv, &x, &y, &dPriv->w, &dPriv->h);
}
static inline void
kopper_present_texture(struct pipe_context *pipe, __DRIdrawable *dPriv,
struct pipe_resource *ptex, struct pipe_box *sub_box)
{
struct dri_drawable *drawable = dri_drawable(dPriv);
struct dri_screen *screen = dri_screen(drawable->sPriv);
screen->base.screen->flush_frontbuffer(screen->base.screen, pipe, ptex, 0, 0, drawable, sub_box);
}
static inline void
kopper_copy_to_front(struct pipe_context *pipe,
__DRIdrawable * dPriv,
struct pipe_resource *ptex)
{
kopper_present_texture(pipe, dPriv, ptex, NULL);
kopper_invalidate_drawable(dPriv);
}
static bool
kopper_flush_frontbuffer(struct dri_context *ctx,
struct dri_drawable *drawable,
enum st_attachment_type statt)
{
struct pipe_resource *ptex;
if (!ctx || statt != ST_ATTACHMENT_FRONT_LEFT)
return false;
if (drawable) {
/* prevent recursion */
if (drawable->flushing)
return true;
drawable->flushing = true;
}
if (drawable->stvis.samples > 1) {
/* Resolve the front buffer. */
dri_pipe_blit(ctx->st->pipe,
drawable->textures[ST_ATTACHMENT_FRONT_LEFT],
drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]);
}
ptex = drawable->textures[statt];
if (ptex) {
ctx->st->pipe->flush_resource(ctx->st->pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]);
struct pipe_screen *screen = drawable->screen->base.screen;
struct st_context_iface *st;
struct pipe_fence_handle *new_fence = NULL;
st = ctx->st;
if (st->thread_finish)
st->thread_finish(st);
st->flush(st, ST_FLUSH_FRONT, &new_fence, NULL, NULL);
if (drawable) {
drawable->flushing = false;
}
/* throttle on the previous fence */
if (drawable->throttle_fence) {
screen->fence_finish(screen, NULL, drawable->throttle_fence, PIPE_TIMEOUT_INFINITE);
screen->fence_reference(screen, &drawable->throttle_fence, NULL);
}
drawable->throttle_fence = new_fence;
kopper_copy_to_front(st->pipe, ctx->dPriv, ptex);
}
return true;
}
static void
kopper_update_tex_buffer(struct dri_drawable *drawable,
struct dri_context *ctx,
struct pipe_resource *res)
{
}
static void
kopper_flush_swapbuffers(struct dri_context *ctx,
struct dri_drawable *drawable)
{
/* does this actually need to do anything? */
}
// XXX this frees its second argument as a side effect - regardless of success
// - since the point is to use it as the superclass initializer before we add
// our own state. kindagross but easier than fixing the object model first.
static struct kopper_drawable *
kopper_create_drawable(__DRIdrawable *dPriv, struct dri_drawable *base)
{
struct kopper_drawable *_ret = CALLOC_STRUCT(kopper_drawable);
if (!_ret)
goto out;
struct dri_drawable *ret = &_ret->base;
// copy all the elements
*ret = *base;
// relocate references to the old struct
ret->base.visual = &ret->stvis;
ret->base.st_manager_private = (void *) ret;
dPriv->driverPrivate = ret;
// and fill in the vtable
ret->allocate_textures = kopper_allocate_textures;
ret->update_drawable_info = kopper_update_drawable_info;
ret->flush_frontbuffer = kopper_flush_frontbuffer;
ret->update_tex_buffer = kopper_update_tex_buffer;
ret->flush_swapbuffers = kopper_flush_swapbuffers;
out:
free(base);
return _ret;
}
static boolean
kopper_create_buffer(__DRIscreen * sPriv,
__DRIdrawable * dPriv,
const struct gl_config *visual, boolean isPixmap)
{
struct kopper_drawable *drawable = NULL;
/* always pass !pixmap because it isn't "handled" or relevant */
if (!dri_create_buffer(sPriv, dPriv, visual, false))
return FALSE;
drawable = kopper_create_drawable(dPriv, dPriv->driverPrivate);
if (!drawable)
return FALSE;
drawable->info.has_alpha = visual->alphaBits > 0;
if (sPriv->kopper_loader->SetSurfaceCreateInfo && !isPixmap)
sPriv->kopper_loader->SetSurfaceCreateInfo(dPriv->loaderPrivate,
&drawable->info);
return TRUE;
}
static void
kopper_swap_buffers(__DRIdrawable *dPriv)
{
struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv);
struct dri_drawable *drawable = dri_drawable(dPriv);
struct pipe_resource *ptex;
if (!ctx)
return;
ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
if (!ptex)
return;
drawable->texture_stamp = dPriv->lastStamp - 1;
dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_CONTEXT, __DRI2_THROTTLE_SWAPBUFFER);
kopper_copy_to_front(ctx->st->pipe, dPriv, ptex);
if (!drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) {
return;
}
/* have to manually swap the pointers here to make frontbuffer readback work */
drawable->textures[ST_ATTACHMENT_BACK_LEFT] = drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
drawable->textures[ST_ATTACHMENT_FRONT_LEFT] = ptex;
}
static __DRIdrawable *
kopperCreateNewDrawable(__DRIscreen *screen,
const __DRIconfig *config,
void *data,
int is_pixmap)
{
__DRIdrawable *pdraw;
assert(data != NULL);
pdraw = malloc(sizeof *pdraw);
if (!pdraw)
return NULL;
pdraw->loaderPrivate = data;
pdraw->driScreenPriv = screen;
pdraw->driContextPriv = NULL;
pdraw->refcount = 0;
pdraw->lastStamp = 0;
pdraw->w = 0;
pdraw->h = 0;
//dri_get_drawable(pdraw);
pdraw->refcount++;
if (!screen->driver->CreateBuffer(screen, pdraw, &config->modes,
is_pixmap)) {
free(pdraw);
return NULL;
}
pdraw->dri2.stamp = pdraw->lastStamp + 1;
return pdraw;
}
const __DRIkopperExtension driKopperExtension = {
.base = { __DRI_KOPPER, 1 },
.createNewDrawable = kopperCreateNewDrawable,
};
const struct __DriverAPIRec galliumvk_driver_api = {
.InitScreen = kopper_init_screen,
.DestroyScreen = dri_destroy_screen,
.CreateBuffer = kopper_create_buffer,
.DestroyBuffer = dri_destroy_buffer,
.SwapBuffers = kopper_swap_buffers,
.CopySubBuffer = NULL,
};
static const struct __DRIDriverVtableExtensionRec galliumvk_vtable = {
.base = { __DRI_DRIVER_VTABLE, 1 },
.vtable = &galliumvk_driver_api,
};
const __DRIextension *galliumvk_driver_extensions[] = {
&driCoreExtension.base,
&driSWRastExtension.base,
&driDRI2Extension.base,
&driImageDriverExtension.base,
&driKopperExtension.base,
&gallium_config_options.base,
&galliumvk_vtable.base,
NULL
};
/* vim: set sw=3 ts=8 sts=3 expandtab: */

View File

@ -45,6 +45,10 @@ if with_dri2
files_libdri += files('dri2.c')
endif
if with_gallium_zink
files_libdri += files('kopper.c')
endif
libdri_c_args = []
if with_gallium_softpipe
libdri_c_args += '-DGALLIUM_SOFTPIPE'
@ -55,7 +59,7 @@ libdri = static_library(
files_libdri,
include_directories : [
inc_include, inc_util, inc_mesa, inc_mapi, inc_src, inc_gallium,
inc_gallium_aux, inc_util,
inc_gallium_aux, inc_util, inc_gallium_drivers,
],
c_args : [libdri_c_args],
gnu_symbol_visibility : 'hidden',

View File

@ -9,7 +9,7 @@ struct sw_winsys;
struct sw_driver_descriptor
{
struct pipe_screen *(*create_screen)(struct sw_winsys *ws, bool sw_vk);
struct pipe_screen *(*create_screen)(struct sw_winsys *ws, const struct pipe_screen_config *config, bool sw_vk);
struct {
const char * const name;
struct sw_winsys *(*create_winsys)();

View File

@ -227,6 +227,10 @@ struct pipe_screen {
struct pipe_resource * (*resource_create)(struct pipe_screen *,
const struct pipe_resource *templat);
struct pipe_resource * (*resource_create_drawable)(struct pipe_screen *,
const struct pipe_resource *tmpl,
const void *loader_private);
struct pipe_resource * (*resource_create_front)(struct pipe_screen *,
const struct pipe_resource *templat,
const void *map_front_private);

View File

@ -124,7 +124,13 @@ DEFINE_LOADER_DRM_ENTRYPOINT(lima)
#endif
#if defined(GALLIUM_ZINK) && !defined(__APPLE__)
DEFINE_LOADER_DRM_ENTRYPOINT(zink);
const __DRIextension **__driDriverGetExtensions_zink(void);
PUBLIC const __DRIextension **__driDriverGetExtensions_zink(void)
{
return galliumvk_driver_extensions;
}
#endif
#if defined(GALLIUM_D3D12)

View File

@ -8,10 +8,10 @@
#include "sw/wrapper/wrapper_sw_winsys.h"
PUBLIC struct pipe_screen *
swrast_create_screen(struct sw_winsys *ws, bool sw_vk);
swrast_create_screen(struct sw_winsys *ws, const struct pipe_screen_config *config, bool sw_vk);
struct pipe_screen *
swrast_create_screen(struct sw_winsys *ws, bool sw_vk)
swrast_create_screen(struct sw_winsys *ws, const struct pipe_screen_config *config, bool sw_vk)
{
struct pipe_screen *screen;

View File

@ -48,6 +48,7 @@
#include "gbmint.h"
#include "loader_dri_helper.h"
#include "kopper_interface.h"
#include "loader.h"
#include "util/debug.h"
#include "util/macros.h"
@ -269,12 +270,19 @@ static const __DRIswrastLoaderExtension swrast_loader_extension = {
.putImage2 = swrast_put_image2
};
static const __DRIkopperLoaderExtension kopper_loader_extension = {
.base = { __DRI_KOPPER_LOADER, 1 },
.SetSurfaceCreateInfo = NULL,
};
static const __DRIextension *gbm_dri_screen_extensions[] = {
&image_lookup_extension.base,
&use_invalidate.base,
&dri2_loader_extension.base,
&image_loader_extension.base,
&swrast_loader_extension.base,
&kopper_loader_extension.base,
NULL,
};
@ -509,15 +517,22 @@ dri_screen_create_sw(struct gbm_dri_device *dri)
char *driver_name;
int ret;
driver_name = strdup("kms_swrast");
driver_name = strdup("zink");
if (!driver_name)
return -errno;
ret = dri_screen_create_dri2(dri, driver_name);
if (ret != 0)
ret = dri_screen_create_swrast(dri);
if (ret != 0)
return ret;
if (ret != 0) {
driver_name = strdup("kms_swrast");
if (!driver_name)
return -errno;
ret = dri_screen_create_dri2(dri, driver_name);
if (ret != 0)
ret = dri_screen_create_swrast(dri);
if (ret != 0)
return ret;
}
dri->software = true;
return 0;