summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nouveau
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nouveau')
-rw-r--r--src/gallium/drivers/nouveau/nouveau_context.c4
-rw-r--r--src/gallium/drivers/nouveau/nouveau_screen.c85
-rw-r--r--src/gallium/drivers/nouveau/nouveau_screen.h12
-rw-r--r--src/gallium/drivers/nouveau/nouveau_util.h100
-rw-r--r--src/gallium/drivers/nouveau/nv04_surface_2d.c34
5 files changed, 210 insertions, 25 deletions
diff --git a/src/gallium/drivers/nouveau/nouveau_context.c b/src/gallium/drivers/nouveau/nouveau_context.c
index 23443869e6..15174983e7 100644
--- a/src/gallium/drivers/nouveau/nouveau_context.c
+++ b/src/gallium/drivers/nouveau/nouveau_context.c
@@ -1,5 +1,5 @@
-#include <pipe/p_defines.h>
-#include <pipe/p_context.h>
+#include "pipe/p_defines.h"
+#include "pipe/p_context.h"
#include "nouveau/nouveau_screen.h"
#include "nouveau/nouveau_context.h"
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c
index 81bc296ab4..b1ad686022 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.c
+++ b/src/gallium/drivers/nouveau/nouveau_screen.c
@@ -1,9 +1,10 @@
-#include <pipe/p_defines.h>
-#include <pipe/p_screen.h>
-#include <pipe/p_state.h>
+#include "pipe/p_defines.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_state.h"
-#include <util/u_memory.h>
-#include <util/u_inlines.h>
+#include "util/u_memory.h"
+#include "util/u_inlines.h"
+#include "util/u_format.h"
#include <stdio.h>
#include <errno.h>
@@ -12,6 +13,9 @@
#include "nouveau_winsys.h"
#include "nouveau_screen.h"
+/* XXX this should go away */
+#include "state_tracker/drm_api.h"
+
static const char *
nouveau_screen_get_name(struct pipe_screen *pscreen)
{
@@ -120,7 +124,7 @@ nouveau_screen_map_flags(unsigned pipe)
if (pipe & PIPE_BUFFER_USAGE_DONTBLOCK)
flags |= NOUVEAU_BO_NOWAIT;
else
- if (pipe & 0 /*PIPE_BUFFER_USAGE_UNSYNCHRONIZED*/)
+ if (pipe & PIPE_BUFFER_USAGE_UNSYNCHRONIZED)
flags |= NOUVEAU_BO_NOSYNC;
return flags;
@@ -231,6 +235,72 @@ nouveau_screen_fence_finish(struct pipe_screen *screen,
return 0;
}
+
+/*
+ * Both texture_{from|get}_handle use drm api defines directly which they
+ * shouldn't do. The problem is that from|get are pipe functions and as
+ * such they should be defined in the pipe level. If nouveau had a propper
+ * winsys interface we would have added from|get to that interface using
+ * the winsys_handle struct as done with other drivers. However this code
+ * calls directly into the libdrm_nouveau.so functions (nouveau_bo_*). So
+ * we need to translate the handle into something they understand.
+ */
+static struct pipe_texture *
+nouveau_screen_texture_from_handle(struct pipe_screen *pscreen,
+ const struct pipe_texture *templ,
+ struct winsys_handle *whandle)
+{
+ struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ struct pipe_texture *pt;
+ struct pipe_buffer *pb;
+ int ret;
+
+ pb = CALLOC(1, sizeof(struct pipe_buffer) + sizeof(struct nouveau_bo*));
+ if (!pb)
+ return NULL;
+
+ ret = nouveau_bo_handle_ref(dev, whandle->handle, (struct nouveau_bo**)(pb+1));
+ if (ret) {
+ debug_printf("%s: ref name 0x%08x failed with %d\n",
+ __func__, whandle->handle, ret);
+ FREE(pb);
+ return NULL;
+ }
+
+ pipe_reference_init(&pb->reference, 1);
+ pb->screen = pscreen;
+ pb->alignment = 0;
+ pb->usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE |
+ PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+ pb->size = nouveau_bo(pb)->size;
+ pt = nouveau_screen(pscreen)->texture_blanket(pscreen, templ,
+ &whandle->stride, pb);
+ pipe_buffer_reference(&pb, NULL);
+ return pt;
+}
+
+static boolean
+nouveau_screen_texture_get_handle(struct pipe_screen *pscreen,
+ struct pipe_texture *pt,
+ struct winsys_handle *whandle)
+{
+ struct nouveau_miptree *mt = nouveau_miptree(pt);
+
+ if (!mt || !mt->bo)
+ return false;
+
+ whandle->stride = util_format_get_stride(mt->base.format, mt->base.width0);
+
+ if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
+ return nouveau_bo_handle_get(mt->bo, &whandle->handle) == 0;
+ } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
+ whandle->handle = mt->bo->handle;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
int
nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
{
@@ -258,6 +328,9 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
pscreen->fence_signalled = nouveau_screen_fence_signalled;
pscreen->fence_finish = nouveau_screen_fence_finish;
+ pscreen->texture_from_handle = nouveau_screen_texture_from_handle;
+ pscreen->texture_get_handle = nouveau_screen_texture_get_handle;
+
return 0;
}
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h
index a7927d88df..f4a7a2bc23 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.h
+++ b/src/gallium/drivers/nouveau/nouveau_screen.h
@@ -6,6 +6,18 @@ struct nouveau_screen {
struct nouveau_device *device;
struct nouveau_channel *channel;
+ /**
+ * Create a new texture object, using the given template info, but on top of
+ * existing memory.
+ *
+ * It is assumed that the buffer data is layed out according to the expected
+ * by the hardware. NULL will be returned if any inconsistency is found.
+ */
+ struct pipe_texture * (*texture_blanket)(struct pipe_screen *,
+ const struct pipe_texture *templat,
+ const unsigned *stride,
+ struct pipe_buffer *buffer);
+
int (*pre_pipebuffer_map_callback) (struct pipe_screen *pscreen,
struct pipe_buffer *pb, unsigned usage);
};
diff --git a/src/gallium/drivers/nouveau/nouveau_util.h b/src/gallium/drivers/nouveau/nouveau_util.h
index a10114beab..7f16e31c3f 100644
--- a/src/gallium/drivers/nouveau/nouveau_util.h
+++ b/src/gallium/drivers/nouveau/nouveau_util.h
@@ -88,4 +88,104 @@ static INLINE unsigned log2i(unsigned i)
return r;
}
+struct u_split_prim {
+ void *priv;
+ void (*emit)(void *priv, unsigned start, unsigned count);
+ void (*edge)(void *priv, boolean enabled);
+
+ unsigned mode;
+ unsigned start;
+ unsigned p_start;
+ unsigned p_end;
+
+ int repeat_first:1;
+ int close_first:1;
+ int edgeflag_off:1;
+};
+
+static inline void
+u_split_prim_init(struct u_split_prim *s,
+ unsigned mode, unsigned start, unsigned count)
+{
+ if (mode == PIPE_PRIM_LINE_LOOP) {
+ s->mode = PIPE_PRIM_LINE_STRIP;
+ s->close_first = 1;
+ } else {
+ s->mode = mode;
+ s->close_first = 0;
+ }
+ s->start = start;
+ s->p_start = start;
+ s->p_end = start + count;
+ s->edgeflag_off = 0;
+ s->repeat_first = 0;
+}
+
+static INLINE boolean
+u_split_prim_next(struct u_split_prim *s, unsigned max_verts)
+{
+ int repeat = 0;
+
+ if (s->repeat_first) {
+ s->emit(s->priv, s->start, 1);
+ max_verts--;
+ if (s->edgeflag_off) {
+ s->edge(s->priv, TRUE);
+ s->edgeflag_off = FALSE;
+ }
+ }
+
+ if (s->p_start + s->close_first + max_verts >= s->p_end) {
+ s->emit(s->priv, s->p_start, s->p_end - s->p_start);
+ if (s->close_first)
+ s->emit(s->priv, s->start, 1);
+ return TRUE;
+ }
+
+ switch (s->mode) {
+ case PIPE_PRIM_LINES:
+ max_verts &= ~1;
+ break;
+ case PIPE_PRIM_LINE_STRIP:
+ repeat = 1;
+ break;
+ case PIPE_PRIM_POLYGON:
+ max_verts--;
+ s->emit(s->priv, s->p_start, max_verts);
+ s->edge(s->priv, FALSE);
+ s->emit(s->priv, s->p_start + max_verts, 1);
+ s->p_start += max_verts;
+ s->repeat_first = TRUE;
+ s->edgeflag_off = TRUE;
+ return FALSE;
+ case PIPE_PRIM_TRIANGLES:
+ max_verts = max_verts - (max_verts % 3);
+ break;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ /* to ensure winding stays correct, always split
+ * on an even number of generated triangles
+ */
+ max_verts = max_verts & ~1;
+ repeat = 2;
+ break;
+ case PIPE_PRIM_TRIANGLE_FAN:
+ s->repeat_first = TRUE;
+ repeat = 1;
+ break;
+ case PIPE_PRIM_QUADS:
+ max_verts &= ~3;
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ max_verts &= ~1;
+ repeat = 2;
+ break;
+ default:
+ break;
+ }
+
+ s->emit (s->priv, s->p_start, max_verts);
+ s->p_start += (max_verts - repeat);
+ return FALSE;
+}
+
#endif
diff --git a/src/gallium/drivers/nouveau/nv04_surface_2d.c b/src/gallium/drivers/nouveau/nv04_surface_2d.c
index 42c2ca932d..b074547c4d 100644
--- a/src/gallium/drivers/nouveau/nv04_surface_2d.c
+++ b/src/gallium/drivers/nouveau/nv04_surface_2d.c
@@ -18,15 +18,15 @@ nv04_surface_format(enum pipe_format format)
case PIPE_FORMAT_I8_UNORM:
return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
case PIPE_FORMAT_R16_SNORM:
- case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_B5G6R5_UNORM:
case PIPE_FORMAT_Z16_UNORM:
- case PIPE_FORMAT_A8L8_UNORM:
+ case PIPE_FORMAT_L8A8_UNORM:
return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
- case PIPE_FORMAT_X8R8G8B8_UNORM:
- case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
- case PIPE_FORMAT_Z24S8_UNORM:
- case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
default:
return -1;
@@ -39,14 +39,14 @@ nv04_rect_format(enum pipe_format format)
switch (format) {
case PIPE_FORMAT_A8_UNORM:
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
- case PIPE_FORMAT_R5G6B5_UNORM:
- case PIPE_FORMAT_A8L8_UNORM:
+ case PIPE_FORMAT_B5G6R5_UNORM:
+ case PIPE_FORMAT_L8A8_UNORM:
case PIPE_FORMAT_Z16_UNORM:
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
- case PIPE_FORMAT_X8R8G8B8_UNORM:
- case PIPE_FORMAT_A8R8G8B8_UNORM:
- case PIPE_FORMAT_Z24S8_UNORM:
- case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
+ case PIPE_FORMAT_X8Z24_UNORM:
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
default:
return -1;
@@ -61,15 +61,15 @@ nv04_scaled_image_format(enum pipe_format format)
case PIPE_FORMAT_L8_UNORM:
case PIPE_FORMAT_I8_UNORM:
return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8;
- case PIPE_FORMAT_A1R5G5B5_UNORM:
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5;
- case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
- case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
- case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_B5G6R5_UNORM:
case PIPE_FORMAT_R16_SNORM:
- case PIPE_FORMAT_A8L8_UNORM:
+ case PIPE_FORMAT_L8A8_UNORM:
return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
default:
return -1;