diff options
Diffstat (limited to 'src/wld/nouveau/nouveau.c')
-rw-r--r-- | src/wld/nouveau/nouveau.c | 941 |
1 files changed, 441 insertions, 500 deletions
diff --git a/src/wld/nouveau/nouveau.c b/src/wld/nouveau/nouveau.c index 7d2e364..baed615 100644 --- a/src/wld/nouveau/nouveau.c +++ b/src/wld/nouveau/nouveau.c @@ -26,53 +26,49 @@ * SOFTWARE. */ +#include "g80_2d.xml.h" +#include "g80_defs.xml.h" +#include "nv_object.xml.h" #include "wld/drm-private.h" #include "wld/drm.h" #include "wld/pixman.h" -#include "nv_object.xml.h" -#include "g80_2d.xml.h" -#include "g80_defs.xml.h" #include <nouveau.h> #include <sys/mman.h> -enum nv_architecture -{ - NV_ARCH_50 = 0x50, - NV_ARCH_C0 = 0xc0, - NV_ARCH_E0 = 0xe0 +enum nv_architecture { + NV_ARCH_50 = 0x50, + NV_ARCH_C0 = 0xc0, + NV_ARCH_E0 = 0xe0 }; -struct nouveau_context -{ - struct wld_context base; - struct nouveau_device * device; - struct nouveau_client * client; - enum nv_architecture architecture; +struct nouveau_context { + struct wld_context base; + struct nouveau_device *device; + struct nouveau_client *client; + enum nv_architecture architecture; }; -struct nouveau_renderer -{ - struct wld_renderer base; - struct nouveau_object * channel; - struct nouveau_pushbuf * pushbuf; - struct nouveau_bufctx * bufctx; - struct nouveau_object * nvc0_2d; +struct nouveau_renderer { + struct wld_renderer base; + struct nouveau_object *channel; + struct nouveau_pushbuf *pushbuf; + struct nouveau_bufctx *bufctx; + struct nouveau_object *nvc0_2d; - struct nouveau_buffer * target; + struct nouveau_buffer *target; }; -struct nouveau_buffer -{ - struct buffer base; - struct wld_exporter exporter; - struct nouveau_context * context; - struct nouveau_bo * bo; +struct nouveau_buffer { + struct buffer base; + struct wld_exporter exporter; + struct nouveau_context *context; + struct nouveau_bo *bo; }; +#include "../interface/buffer.h" #include "../interface/context.h" #include "../interface/renderer.h" -#include "../interface/buffer.h" #define DRM_DRIVER_NAME nouveau #include "../interface/drm.h" IMPL(nouveau_context, wld_context) @@ -80,599 +76,544 @@ IMPL(nouveau_renderer, wld_renderer) IMPL(nouveau_buffer, wld_buffer) /**** DRM driver ****/ -bool driver_device_supported(uint32_t vendor_id, uint32_t device_id) -{ - return vendor_id == 0x10de; +bool driver_device_supported(uint32_t vendor_id, uint32_t device_id) { + return vendor_id == 0x10de; } -struct wld_context * driver_create_context(int drm_fd) -{ - struct nouveau_context * context; - - if (!(context = malloc(sizeof *context))) - goto error0; - - if (nouveau_device_wrap(drm_fd, 0, &context->device) != 0) - goto error1; - - switch (context->device->chipset & ~0xf) - { - /* TODO: Support NV50 - case 0x50: - case 0x80: - case 0x90: - case 0xa0: - context->architecture = NV_ARCH_50; - break; - */ - case 0xc0: - case 0xd0: - context->architecture = NV_ARCH_C0; - break; - /* TODO: Support NVE0 - case 0xe0: - case 0xf0: - case 0x100: - context->architecture = NV_ARCH_E0; - break; - */ - default: - return NULL; - } +struct wld_context *driver_create_context(int drm_fd) { + struct nouveau_context *context; + + if (!(context = malloc(sizeof *context))) + goto error0; + + if (nouveau_device_wrap(drm_fd, 0, &context->device) != 0) + goto error1; + + switch (context->device->chipset & ~0xf) { + /* TODO: Support NV50 + case 0x50: + case 0x80: + case 0x90: + case 0xa0: + context->architecture = NV_ARCH_50; + break; + */ + case 0xc0: + case 0xd0: + context->architecture = NV_ARCH_C0; + break; + /* TODO: Support NVE0 + case 0xe0: + case 0xf0: + case 0x100: + context->architecture = NV_ARCH_E0; + break; + */ + default: + return NULL; + } - if (nouveau_client_new(context->device, &context->client) != 0) - goto error2; + if (nouveau_client_new(context->device, &context->client) != 0) + goto error2; - context_initialize(&context->base, &wld_context_impl); + context_initialize(&context->base, &wld_context_impl); - return &context->base; + return &context->base; - error2: - nouveau_device_del(&context->device); - error1: - free(context); - error0: - return NULL; +error2: + nouveau_device_del(&context->device); +error1: + free(context); +error0: + return NULL; } /**** Context ****/ -static inline bool ensure_space(struct nouveau_pushbuf * push, uint32_t count) -{ - if (push->end - push->cur > count) - return true; +static inline bool ensure_space(struct nouveau_pushbuf *push, uint32_t count) { + if (push->end - push->cur > count) + return true; - return nouveau_pushbuf_space(push, count, 0, 0) == 0; + return nouveau_pushbuf_space(push, count, 0, 0) == 0; } -static inline void nv_add_dword(struct nouveau_pushbuf * push, uint32_t dword) -{ - *push->cur++ = dword; +static inline void nv_add_dword(struct nouveau_pushbuf *push, uint32_t dword) { + *push->cur++ = dword; } -static inline void nv_add_dwords_va(struct nouveau_pushbuf * push, - uint16_t count, va_list dwords) -{ - while (count--) - nv_add_dword(push, va_arg(dwords, uint32_t)); +static inline void nv_add_dwords_va(struct nouveau_pushbuf *push, + uint16_t count, va_list dwords) { + while (count--) + nv_add_dword(push, va_arg(dwords, uint32_t)); } -static inline void nv_add_data(struct nouveau_pushbuf * push, - void * data, uint32_t count) -{ - memcpy(push->cur, data, count * 4); - push->cur += count; +static inline void nv_add_data(struct nouveau_pushbuf *push, void *data, + uint32_t count) { + memcpy(push->cur, data, count * 4); + push->cur += count; } -static inline uint32_t nvc0_format(uint32_t format) -{ - switch (format) - { - case WLD_FORMAT_XRGB8888: - return G80_SURFACE_FORMAT_BGRX8_UNORM; - case WLD_FORMAT_ARGB8888: - return G80_SURFACE_FORMAT_BGRA8_UNORM; - } +static inline uint32_t nvc0_format(uint32_t format) { + switch (format) { + case WLD_FORMAT_XRGB8888: + return G80_SURFACE_FORMAT_BGRX8_UNORM; + case WLD_FORMAT_ARGB8888: + return G80_SURFACE_FORMAT_BGRA8_UNORM; + } - return 0; + return 0; } -enum -{ - GF100_COMMAND_TYPE_INCREASING = 1, - GF100_COMMAND_TYPE_NON_INCREASING = 3, - GF100_COMMAND_TYPE_INLINE = 4 +enum { + GF100_COMMAND_TYPE_INCREASING = 1, + GF100_COMMAND_TYPE_NON_INCREASING = 3, + GF100_COMMAND_TYPE_INLINE = 4 }; -enum -{ - GF100_SUBCHANNEL_2D = 3, +enum { + GF100_SUBCHANNEL_2D = 3, }; static inline uint32_t nvc0_command(uint8_t type, uint8_t subchannel, - uint16_t method, uint16_t count_or_value) -{ - return type << 29 | count_or_value << 16 | subchannel << 13 | method >> 2; + uint16_t method, uint16_t count_or_value) { + return type << 29 | count_or_value << 16 | subchannel << 13 | method >> 2; } -static inline void nvc0_inline(struct nouveau_pushbuf * push, - uint8_t subchannel, uint16_t method, - uint16_t value) -{ - nv_add_dword(push, nvc0_command(GF100_COMMAND_TYPE_INLINE, - subchannel, method, value)); +static inline void nvc0_inline(struct nouveau_pushbuf *push, uint8_t subchannel, + uint16_t method, uint16_t value) { + nv_add_dword( + push, nvc0_command(GF100_COMMAND_TYPE_INLINE, subchannel, method, value)); } -static inline void nvc0_methods(struct nouveau_pushbuf * push, +static inline void nvc0_methods(struct nouveau_pushbuf *push, uint8_t subchannel, uint16_t start_method, - uint16_t count, ...) -{ - va_list dwords; - nv_add_dword(push, nvc0_command(GF100_COMMAND_TYPE_INCREASING, - subchannel, start_method, count)); - va_start(dwords, count); - nv_add_dwords_va(push, count, dwords); - va_end(dwords); + uint16_t count, ...) { + va_list dwords; + nv_add_dword(push, nvc0_command(GF100_COMMAND_TYPE_INCREASING, subchannel, + start_method, count)); + va_start(dwords, count); + nv_add_dwords_va(push, count, dwords); + va_end(dwords); } -#define nvc0_2d(push, method, count, ...) \ - nvc0_methods(push, GF100_SUBCHANNEL_2D, method, count, __VA_ARGS__) -#define nvc0_2d_inline(push, method, value) \ - nvc0_inline(push, GF100_SUBCHANNEL_2D, method, value) +#define nvc0_2d(push, method, count, ...) \ + nvc0_methods(push, GF100_SUBCHANNEL_2D, method, count, __VA_ARGS__) +#define nvc0_2d_inline(push, method, value) \ + nvc0_inline(push, GF100_SUBCHANNEL_2D, method, value) -static bool nvc0_2d_initialize(struct nouveau_renderer * renderer) -{ - int ret; +static bool nvc0_2d_initialize(struct nouveau_renderer *renderer) { + int ret; - ret = nouveau_object_new(renderer->channel, GF100_2D, GF100_2D, NULL, 0, - &renderer->nvc0_2d); + ret = nouveau_object_new(renderer->channel, GF100_2D, GF100_2D, NULL, 0, + &renderer->nvc0_2d); - if (ret != 0) - goto error0; + if (ret != 0) + goto error0; - if (!ensure_space(renderer->pushbuf, 5)) - goto error1; + if (!ensure_space(renderer->pushbuf, 5)) + goto error1; - nvc0_2d(renderer->pushbuf, NV1_SUBCHAN_OBJECT, 1, - renderer->nvc0_2d->handle); - nvc0_2d_inline(renderer->pushbuf, G80_2D_OPERATION, - G80_2D_OPERATION_SRCCOPY_AND); - nvc0_2d_inline(renderer->pushbuf, G80_2D_UNK0884, 0x3f); - nvc0_2d_inline(renderer->pushbuf, G80_2D_UNK0888, 1); + nvc0_2d(renderer->pushbuf, NV1_SUBCHAN_OBJECT, 1, renderer->nvc0_2d->handle); + nvc0_2d_inline(renderer->pushbuf, G80_2D_OPERATION, + G80_2D_OPERATION_SRCCOPY_AND); + nvc0_2d_inline(renderer->pushbuf, G80_2D_UNK0884, 0x3f); + nvc0_2d_inline(renderer->pushbuf, G80_2D_UNK0888, 1); - return true; + return true; - error1: - nouveau_object_del(&renderer->nvc0_2d); - error0: - return false; +error1: + nouveau_object_del(&renderer->nvc0_2d); +error0: + return false; } -static void nvc0_2d_finalize(struct nouveau_renderer * renderer) -{ - nouveau_object_del(&renderer->nvc0_2d); +static void nvc0_2d_finalize(struct nouveau_renderer *renderer) { + nouveau_object_del(&renderer->nvc0_2d); } -struct wld_renderer * context_create_renderer(struct wld_context * base) -{ - struct nouveau_context * context = nouveau_context(base); - struct nouveau_renderer * renderer; - struct nvc0_fifo fifo = { }; - int ret; +struct wld_renderer *context_create_renderer(struct wld_context *base) { + struct nouveau_context *context = nouveau_context(base); + struct nouveau_renderer *renderer; + struct nvc0_fifo fifo = {}; + int ret; - if (!(renderer = malloc(sizeof *renderer))) - goto error0; + if (!(renderer = malloc(sizeof *renderer))) + goto error0; - ret = nouveau_object_new(&context->device->object, 0, - NOUVEAU_FIFO_CHANNEL_CLASS, &fifo, sizeof fifo, - &renderer->channel); + ret = nouveau_object_new(&context->device->object, 0, + NOUVEAU_FIFO_CHANNEL_CLASS, &fifo, sizeof fifo, + &renderer->channel); - if (ret != 0) - goto error1; + if (ret != 0) + goto error1; - ret = nouveau_pushbuf_new(context->client, renderer->channel, 4, 32 * 1024, - true, &renderer->pushbuf); + ret = nouveau_pushbuf_new(context->client, renderer->channel, 4, 32 * 1024, + true, &renderer->pushbuf); - if (ret != 0) - goto error2; + if (ret != 0) + goto error2; - if (nouveau_bufctx_new(context->client, 1, &renderer->bufctx) != 0) - goto error3; + if (nouveau_bufctx_new(context->client, 1, &renderer->bufctx) != 0) + goto error3; - if (!nvc0_2d_initialize(renderer)) - goto error4; + if (!nvc0_2d_initialize(renderer)) + goto error4; - renderer_initialize(&renderer->base, &wld_renderer_impl); - renderer->target = NULL; + renderer_initialize(&renderer->base, &wld_renderer_impl); + renderer->target = NULL; - return &renderer->base; + return &renderer->base; - error4: - nouveau_bufctx_del(&renderer->bufctx); - error3: - nouveau_pushbuf_del(&renderer->pushbuf); - error2: - nouveau_object_del(&renderer->channel); - error1: - free(renderer); - error0: - return NULL; +error4: + nouveau_bufctx_del(&renderer->bufctx); +error3: + nouveau_pushbuf_del(&renderer->pushbuf); +error2: + nouveau_object_del(&renderer->channel); +error1: + free(renderer); +error0: + return NULL; } -static bool export(struct wld_exporter * exporter, struct wld_buffer * base, - uint32_t type, union wld_object * object) -{ - struct nouveau_buffer * buffer = nouveau_buffer(base); - - switch (type) - { - case WLD_DRM_OBJECT_HANDLE: - object->u32 = buffer->bo->handle; - return true; - case WLD_DRM_OBJECT_PRIME_FD: - if (nouveau_bo_set_prime(buffer->bo, &object->i) != 0) - return false; - return true; - default: - return false; - } +static bool export(struct wld_exporter *exporter, struct wld_buffer *base, + uint32_t type, union wld_object *object) { + struct nouveau_buffer *buffer = nouveau_buffer(base); + + switch (type) { + case WLD_DRM_OBJECT_HANDLE: + object->u32 = buffer->bo->handle; + return true; + case WLD_DRM_OBJECT_PRIME_FD: + if (nouveau_bo_set_prime(buffer->bo, &object->i) != 0) + return false; + return true; + default: + return false; + } } -static struct nouveau_buffer * new_buffer(struct nouveau_context * context, - uint32_t width, uint32_t height, - uint32_t format, uint32_t pitch) -{ - struct nouveau_buffer * buffer; +static struct nouveau_buffer *new_buffer(struct nouveau_context *context, + uint32_t width, uint32_t height, + uint32_t format, uint32_t pitch) { + struct nouveau_buffer *buffer; - if (!(buffer = malloc(sizeof *buffer))) - return NULL; + if (!(buffer = malloc(sizeof *buffer))) + return NULL; - buffer_initialize(&buffer->base, &wld_buffer_impl, - width, height, format, pitch); - buffer->context = context; - buffer->exporter.export = &export; - wld_buffer_add_exporter(&buffer->base.base, &buffer->exporter); + buffer_initialize(&buffer->base, &wld_buffer_impl, width, height, format, + pitch); + buffer->context = context; + buffer->exporter.export = &export; + wld_buffer_add_exporter(&buffer->base.base, &buffer->exporter); - return buffer; + return buffer; } -static inline uint32_t roundup(uint32_t value, uint32_t alignment) -{ - return (value + alignment - 1) & ~(alignment - 1); +static inline uint32_t roundup(uint32_t value, uint32_t alignment) { + return (value + alignment - 1) & ~(alignment - 1); } -struct buffer * context_create_buffer(struct wld_context * base, - uint32_t width, uint32_t height, - uint32_t format, uint32_t flags) -{ - struct nouveau_context * context = nouveau_context(base); - struct nouveau_buffer * buffer; - uint32_t bpp = format_bytes_per_pixel(format), - pitch = roundup(width * bpp, 64), bo_flags; - union nouveau_bo_config config = { }; - - if (!(buffer = new_buffer(context, width, height, format, pitch))) - goto error0; - - bo_flags = NOUVEAU_BO_VRAM; - - if (flags & WLD_DRM_FLAG_SCANOUT) - bo_flags |= NOUVEAU_BO_CONTIG; - - if (height > 0x40 && !(flags & WLD_FLAG_MAP)) - { - config.nvc0.tile_mode = 0x40; - config.nvc0.memtype = 0xfe; - height = roundup(height, 0x80); - } - else - bo_flags |= NOUVEAU_BO_MAP; - - if (nouveau_bo_new(context->device, bo_flags, 0, pitch * height, - &config, &buffer->bo) != 0) - { - goto error1; - } - - return &buffer->base; - - error1: - free(buffer); - error0: - return NULL; +struct buffer *context_create_buffer(struct wld_context *base, uint32_t width, + uint32_t height, uint32_t format, + uint32_t flags) { + struct nouveau_context *context = nouveau_context(base); + struct nouveau_buffer *buffer; + uint32_t bpp = format_bytes_per_pixel(format), + pitch = roundup(width * bpp, 64), bo_flags; + union nouveau_bo_config config = {}; + + if (!(buffer = new_buffer(context, width, height, format, pitch))) + goto error0; + + bo_flags = NOUVEAU_BO_VRAM; + + if (flags & WLD_DRM_FLAG_SCANOUT) + bo_flags |= NOUVEAU_BO_CONTIG; + + if (height > 0x40 && !(flags & WLD_FLAG_MAP)) { + config.nvc0.tile_mode = 0x40; + config.nvc0.memtype = 0xfe; + height = roundup(height, 0x80); + } else + bo_flags |= NOUVEAU_BO_MAP; + + if (nouveau_bo_new(context->device, bo_flags, 0, pitch * height, &config, + &buffer->bo) != 0) { + goto error1; + } + + return &buffer->base; + +error1: + free(buffer); +error0: + return NULL; } -struct buffer * context_import_buffer(struct wld_context * base, - uint32_t type, union wld_object object, - uint32_t width, uint32_t height, - uint32_t format, uint32_t pitch) -{ - struct nouveau_context * context = (void *) base; - struct nouveau_buffer * buffer; - struct nouveau_bo * bo = NULL; - - switch (type) - { - case WLD_DRM_OBJECT_PRIME_FD: - if (nouveau_bo_prime_handle_ref(context->device, - object.i, &bo) != 0) - { - goto error0; - } - break; - default: goto error0; +struct buffer *context_import_buffer(struct wld_context *base, uint32_t type, + union wld_object object, uint32_t width, + uint32_t height, uint32_t format, + uint32_t pitch) { + struct nouveau_context *context = (void *)base; + struct nouveau_buffer *buffer; + struct nouveau_bo *bo = NULL; + + switch (type) { + case WLD_DRM_OBJECT_PRIME_FD: + if (nouveau_bo_prime_handle_ref(context->device, object.i, &bo) != 0) { + goto error0; } + break; + default: + goto error0; + } - if (!(buffer = new_buffer(context, width, height, format, pitch))) - goto error1; + if (!(buffer = new_buffer(context, width, height, format, pitch))) + goto error1; - buffer->bo = bo; + buffer->bo = bo; - return &buffer->base; + return &buffer->base; - error1: - nouveau_bo_ref(NULL, &buffer->bo); - error0: - return NULL; +error1: + nouveau_bo_ref(NULL, &buffer->bo); +error0: + return NULL; } -void context_destroy(struct wld_context * base) -{ - struct nouveau_context * context = nouveau_context(base); +void context_destroy(struct wld_context *base) { + struct nouveau_context *context = nouveau_context(base); - nouveau_client_del(&context->client); - nouveau_device_del(&context->device); - free(context); + nouveau_client_del(&context->client); + nouveau_device_del(&context->device); + free(context); } /**** Renderer ****/ -uint32_t renderer_capabilities(struct wld_renderer * renderer, - struct buffer * buffer) -{ - if (buffer->base.impl == &wld_buffer_impl) - return WLD_CAPABILITY_READ | WLD_CAPABILITY_WRITE; +uint32_t renderer_capabilities(struct wld_renderer *renderer, + struct buffer *buffer) { + if (buffer->base.impl == &wld_buffer_impl) + return WLD_CAPABILITY_READ | WLD_CAPABILITY_WRITE; - return 0; + return 0; } -bool renderer_set_target(struct wld_renderer * base, struct buffer * buffer) -{ - struct nouveau_renderer * renderer = nouveau_renderer(base); +bool renderer_set_target(struct wld_renderer *base, struct buffer *buffer) { + struct nouveau_renderer *renderer = nouveau_renderer(base); - if (buffer && buffer->base.impl != &wld_buffer_impl) - return false; + if (buffer && buffer->base.impl != &wld_buffer_impl) + return false; - renderer->target = buffer ? nouveau_buffer(&buffer->base) : NULL; + renderer->target = buffer ? nouveau_buffer(&buffer->base) : NULL; - return true; + return true; } -static inline void nvc0_2d_use_buffer(struct nouveau_renderer * renderer, - struct nouveau_buffer * buffer, - uint16_t format_method, uint16_t format) -{ - uint32_t access = format == G80_2D_SRC_FORMAT ? NOUVEAU_BO_RD - : NOUVEAU_BO_WR; - - nvc0_2d_inline(renderer->pushbuf, format_method, format); - - if (buffer->bo->config.nvc0.memtype) - { - nvc0_2d(renderer->pushbuf, format_method + 0x04, 2, - 0, buffer->bo->config.nvc0.tile_mode); - } - else - { - nvc0_2d_inline(renderer->pushbuf, format_method + 0x04, 1); - nvc0_2d(renderer->pushbuf, format_method + 0x14, 1, - buffer->base.base.pitch); - } - - nvc0_2d(renderer->pushbuf, format_method + 0x18, 4, - buffer->base.base.width, buffer->base.base.height, - buffer->bo->offset >> 32, buffer->bo->offset); - nouveau_bufctx_refn(renderer->bufctx, 0, buffer->bo, - NOUVEAU_BO_VRAM | access); +static inline void nvc0_2d_use_buffer(struct nouveau_renderer *renderer, + struct nouveau_buffer *buffer, + uint16_t format_method, uint16_t format) { + uint32_t access = format == G80_2D_SRC_FORMAT ? NOUVEAU_BO_RD : NOUVEAU_BO_WR; + + nvc0_2d_inline(renderer->pushbuf, format_method, format); + + if (buffer->bo->config.nvc0.memtype) { + nvc0_2d(renderer->pushbuf, format_method + 0x04, 2, 0, + buffer->bo->config.nvc0.tile_mode); + } else { + nvc0_2d_inline(renderer->pushbuf, format_method + 0x04, 1); + nvc0_2d(renderer->pushbuf, format_method + 0x14, 1, + buffer->base.base.pitch); + } + + nvc0_2d(renderer->pushbuf, format_method + 0x18, 4, buffer->base.base.width, + buffer->base.base.height, buffer->bo->offset >> 32, + buffer->bo->offset); + nouveau_bufctx_refn(renderer->bufctx, 0, buffer->bo, + NOUVEAU_BO_VRAM | access); } -void renderer_fill_rectangle(struct wld_renderer * base, uint32_t color, - int32_t x, int32_t y, - uint32_t width, uint32_t height) -{ - struct nouveau_renderer * renderer = nouveau_renderer(base); - struct nouveau_buffer * dst = renderer->target; - uint32_t format; +void renderer_fill_rectangle(struct wld_renderer *base, uint32_t color, + int32_t x, int32_t y, uint32_t width, + uint32_t height) { + struct nouveau_renderer *renderer = nouveau_renderer(base); + struct nouveau_buffer *dst = renderer->target; + uint32_t format; - if (!ensure_space(renderer->pushbuf, 18)) - return; + if (!ensure_space(renderer->pushbuf, 18)) + return; - format = nvc0_format(dst->base.base.format); + format = nvc0_format(dst->base.base.format); - nouveau_bufctx_reset(renderer->bufctx, 0); - nvc0_2d_use_buffer(renderer, dst, G80_2D_DST_FORMAT, format); - nvc0_2d(renderer->pushbuf, G80_2D_DRAW_SHAPE, 3, - G80_2D_DRAW_SHAPE_RECTANGLES, format, color); - nouveau_pushbuf_bufctx(renderer->pushbuf, renderer->bufctx); + nouveau_bufctx_reset(renderer->bufctx, 0); + nvc0_2d_use_buffer(renderer, dst, G80_2D_DST_FORMAT, format); + nvc0_2d(renderer->pushbuf, G80_2D_DRAW_SHAPE, 3, G80_2D_DRAW_SHAPE_RECTANGLES, + format, color); + nouveau_pushbuf_bufctx(renderer->pushbuf, renderer->bufctx); - if (nouveau_pushbuf_validate(renderer->pushbuf) != 0) - return; + if (nouveau_pushbuf_validate(renderer->pushbuf) != 0) + return; - nvc0_2d(renderer->pushbuf, G80_2D_DRAW_POINT32_X(0), 4, - x, y, x + width, y + height); + nvc0_2d(renderer->pushbuf, G80_2D_DRAW_POINT32_X(0), 4, x, y, x + width, + y + height); } -void renderer_copy_rectangle(struct wld_renderer * base, - struct buffer * buffer_base, - int32_t dst_x, int32_t dst_y, - int32_t src_x, int32_t src_y, - uint32_t width, uint32_t height) -{ - struct nouveau_renderer * renderer = nouveau_renderer(base); +void renderer_copy_rectangle(struct wld_renderer *base, + struct buffer *buffer_base, int32_t dst_x, + int32_t dst_y, int32_t src_x, int32_t src_y, + uint32_t width, uint32_t height) { + struct nouveau_renderer *renderer = nouveau_renderer(base); - if (buffer_base->base.impl != &wld_buffer_impl) - return; + if (buffer_base->base.impl != &wld_buffer_impl) + return; - struct nouveau_buffer * src = nouveau_buffer(&buffer_base->base), - * dst = renderer->target; - uint32_t src_format, dst_format; + struct nouveau_buffer *src = nouveau_buffer(&buffer_base->base), + *dst = renderer->target; + uint32_t src_format, dst_format; - if (!ensure_space(renderer->pushbuf, 33)) - return; + if (!ensure_space(renderer->pushbuf, 33)) + return; - src_format = nvc0_format(src->base.base.format); - dst_format = nvc0_format(dst->base.base.format); + src_format = nvc0_format(src->base.base.format); + dst_format = nvc0_format(dst->base.base.format); - nouveau_bufctx_reset(renderer->bufctx, 0); - nvc0_2d_use_buffer(renderer, src, G80_2D_SRC_FORMAT, src_format); - nvc0_2d_use_buffer(renderer, dst, G80_2D_DST_FORMAT, dst_format); - nouveau_pushbuf_bufctx(renderer->pushbuf, renderer->bufctx); + nouveau_bufctx_reset(renderer->bufctx, 0); + nvc0_2d_use_buffer(renderer, src, G80_2D_SRC_FORMAT, src_format); + nvc0_2d_use_buffer(renderer, dst, G80_2D_DST_FORMAT, dst_format); + nouveau_pushbuf_bufctx(renderer->pushbuf, renderer->bufctx); - if (nouveau_pushbuf_validate(renderer->pushbuf) != 0) - return; + if (nouveau_pushbuf_validate(renderer->pushbuf) != 0) + return; - nvc0_2d_inline(renderer->pushbuf, G80_GRAPH_SERIALIZE, 0); - nvc0_2d_inline(renderer->pushbuf, G80_2D_BLIT_CONTROL, - G80_2D_BLIT_CONTROL_ORIGIN_CENTER - | G80_2D_BLIT_CONTROL_FILTER_POINT_SAMPLE); - nvc0_2d(renderer->pushbuf, G80_2D_BLIT_DST_X, 12, - dst_x, dst_y, width, height, 0, 1, 0, 1, 0, src_x, 0, src_y); + nvc0_2d_inline(renderer->pushbuf, G80_GRAPH_SERIALIZE, 0); + nvc0_2d_inline(renderer->pushbuf, G80_2D_BLIT_CONTROL, + G80_2D_BLIT_CONTROL_ORIGIN_CENTER | + G80_2D_BLIT_CONTROL_FILTER_POINT_SAMPLE); + nvc0_2d(renderer->pushbuf, G80_2D_BLIT_DST_X, 12, dst_x, dst_y, width, height, + 0, 1, 0, 1, 0, src_x, 0, src_y); - renderer_flush(base); + renderer_flush(base); } -void renderer_draw_text(struct wld_renderer * base, - struct font * font, uint32_t color, - int32_t x, int32_t y, const char * text, - uint32_t length, struct wld_extents * extents) -{ - struct nouveau_renderer * renderer = nouveau_renderer(base); - struct nouveau_buffer * dst = renderer->target; - uint32_t format; - int ret; - struct glyph * glyph; - FT_UInt glyph_index; - uint32_t c, count; - int32_t origin_x = x; - - if (!ensure_space(renderer->pushbuf, 17)) - return; - - format = nvc0_format(dst->base.base.format); - - nouveau_bufctx_reset(renderer->bufctx, 0); - nvc0_2d_use_buffer(renderer, dst, G80_2D_DST_FORMAT, format); - nvc0_2d_inline(renderer->pushbuf, G80_2D_SIFC_BITMAP_ENABLE, 1); - nvc0_2d(renderer->pushbuf, G80_2D_SIFC_BITMAP_FORMAT, 6, - G80_2D_SIFC_BITMAP_FORMAT_I1, - 0, /* SIFC_FORMAT */ - G80_2D_SIFC_BITMAP_LINE_PACK_MODE_ALIGN_BYTE, - 0, color, /* SIFC_BITMAP_COLOR_BIT0, SIFC_BITMAP_COLOR_BIT1 */ - 0 /* SIFC_BITMAP_WRITE_BIT0_ENABLE */ - ); - nouveau_pushbuf_bufctx(renderer->pushbuf, renderer->bufctx); - - if (nouveau_pushbuf_validate(renderer->pushbuf) != 0) - return; - - if (length == -1) - length = strlen(text); - - while ((ret = FcUtf8ToUcs4((FcChar8 *) text, &c, length)) > 0 && c != '\0') - { - text += ret; - length -= ret; - glyph_index = FT_Get_Char_Index(font->face, c); - - if (!font_ensure_glyph(font, glyph_index)) - continue; - - glyph = font->glyphs[glyph_index]; - - if (glyph->bitmap.width == 0 || glyph->bitmap.rows == 0) - goto advance; - - count = (glyph->bitmap.pitch * glyph->bitmap.rows + 3) / 4; - - if (!ensure_space(renderer->pushbuf, 12 + count)) - return; - - nvc0_2d(renderer->pushbuf, G80_2D_SIFC_WIDTH, 10, - /* Use the pitch instead of width to ensure the correct - * alignment is used. */ - glyph->bitmap.pitch * 8, glyph->bitmap.rows, - 0, 1, 0, 1, - 0, origin_x + glyph->x, 0, y + glyph->y); - nv_add_dword(renderer->pushbuf, - nvc0_command(GF100_COMMAND_TYPE_NON_INCREASING, - GF100_SUBCHANNEL_2D, - G80_2D_SIFC_DATA, count)); - nv_add_data(renderer->pushbuf, glyph->bitmap.buffer, count); - - advance: - origin_x += glyph->advance; - } - - if (extents) - extents->advance = origin_x - x; +void renderer_draw_text(struct wld_renderer *base, struct font *font, + uint32_t color, int32_t x, int32_t y, const char *text, + uint32_t length, struct wld_extents *extents) { + struct nouveau_renderer *renderer = nouveau_renderer(base); + struct nouveau_buffer *dst = renderer->target; + uint32_t format; + int ret; + struct glyph *glyph; + FT_UInt glyph_index; + uint32_t c, count; + int32_t origin_x = x; + + if (!ensure_space(renderer->pushbuf, 17)) + return; + + format = nvc0_format(dst->base.base.format); + + nouveau_bufctx_reset(renderer->bufctx, 0); + nvc0_2d_use_buffer(renderer, dst, G80_2D_DST_FORMAT, format); + nvc0_2d_inline(renderer->pushbuf, G80_2D_SIFC_BITMAP_ENABLE, 1); + nvc0_2d(renderer->pushbuf, G80_2D_SIFC_BITMAP_FORMAT, 6, + G80_2D_SIFC_BITMAP_FORMAT_I1, 0, /* SIFC_FORMAT */ + G80_2D_SIFC_BITMAP_LINE_PACK_MODE_ALIGN_BYTE, 0, + color, /* SIFC_BITMAP_COLOR_BIT0, SIFC_BITMAP_COLOR_BIT1 */ + 0 /* SIFC_BITMAP_WRITE_BIT0_ENABLE */ + ); + nouveau_pushbuf_bufctx(renderer->pushbuf, renderer->bufctx); + + if (nouveau_pushbuf_validate(renderer->pushbuf) != 0) + return; + + if (length == -1) + length = strlen(text); + + while ((ret = FcUtf8ToUcs4((FcChar8 *)text, &c, length)) > 0 && c != '\0') { + text += ret; + length -= ret; + glyph_index = FT_Get_Char_Index(font->face, c); + + if (!font_ensure_glyph(font, glyph_index)) + continue; + + glyph = font->glyphs[glyph_index]; + + if (glyph->bitmap.width == 0 || glyph->bitmap.rows == 0) + goto advance; + + count = (glyph->bitmap.pitch * glyph->bitmap.rows + 3) / 4; + + if (!ensure_space(renderer->pushbuf, 12 + count)) + return; + + nvc0_2d(renderer->pushbuf, G80_2D_SIFC_WIDTH, 10, + /* Use the pitch instead of width to ensure the correct + * alignment is used. */ + glyph->bitmap.pitch * 8, glyph->bitmap.rows, 0, 1, 0, 1, 0, + origin_x + glyph->x, 0, y + glyph->y); + nv_add_dword(renderer->pushbuf, + nvc0_command(GF100_COMMAND_TYPE_NON_INCREASING, + GF100_SUBCHANNEL_2D, G80_2D_SIFC_DATA, count)); + nv_add_data(renderer->pushbuf, glyph->bitmap.buffer, count); + + advance: + origin_x += glyph->advance; + } + + if (extents) + extents->advance = origin_x - x; } -void renderer_flush(struct wld_renderer * base) -{ - struct nouveau_renderer * renderer = nouveau_renderer(base); +void renderer_flush(struct wld_renderer *base) { + struct nouveau_renderer *renderer = nouveau_renderer(base); - nouveau_pushbuf_kick(renderer->pushbuf, renderer->channel); - nouveau_pushbuf_bufctx(renderer->pushbuf, NULL); + nouveau_pushbuf_kick(renderer->pushbuf, renderer->channel); + nouveau_pushbuf_bufctx(renderer->pushbuf, NULL); } -void renderer_destroy(struct wld_renderer * base) -{ - struct nouveau_renderer * renderer = nouveau_renderer(base); +void renderer_destroy(struct wld_renderer *base) { + struct nouveau_renderer *renderer = nouveau_renderer(base); - nvc0_2d_finalize(renderer); - nouveau_bufctx_del(&renderer->bufctx); - nouveau_pushbuf_del(&renderer->pushbuf); - nouveau_object_del(&renderer->channel); - free(renderer); + nvc0_2d_finalize(renderer); + nouveau_bufctx_del(&renderer->bufctx); + nouveau_pushbuf_del(&renderer->pushbuf); + nouveau_object_del(&renderer->channel); + free(renderer); } /**** Buffer ****/ -bool buffer_map(struct buffer * base) -{ - struct nouveau_buffer * buffer = nouveau_buffer(&base->base); - - /* If the buffer is tiled, it cannot be mapped into virtual memory in order - * to appear linear like intel can do with map_gtt. */ - if (buffer->bo->config.nvc0.tile_mode) - return false; - - if (nouveau_bo_map(buffer->bo, NOUVEAU_BO_WR, - buffer->context->client) != 0) - { - return false; - } +bool buffer_map(struct buffer *base) { + struct nouveau_buffer *buffer = nouveau_buffer(&base->base); - buffer->base.base.map = buffer->bo->map; + /* If the buffer is tiled, it cannot be mapped into virtual memory in order + * to appear linear like intel can do with map_gtt. */ + if (buffer->bo->config.nvc0.tile_mode) + return false; - return true; + if (nouveau_bo_map(buffer->bo, NOUVEAU_BO_WR, buffer->context->client) != 0) { + return false; + } + + buffer->base.base.map = buffer->bo->map; + + return true; } -bool buffer_unmap(struct buffer * base) -{ - struct nouveau_buffer * buffer = nouveau_buffer(&base->base); +bool buffer_unmap(struct buffer *base) { + struct nouveau_buffer *buffer = nouveau_buffer(&base->base); - if (munmap(buffer->bo->map, buffer->bo->size) == -1) - return false; + if (munmap(buffer->bo->map, buffer->bo->size) == -1) + return false; - buffer->bo->map = NULL; - base->base.map = NULL; + buffer->bo->map = NULL; + base->base.map = NULL; - return true; + return true; } -void buffer_destroy(struct buffer * base) -{ - struct nouveau_buffer * buffer = nouveau_buffer(&base->base); +void buffer_destroy(struct buffer *base) { + struct nouveau_buffer *buffer = nouveau_buffer(&base->base); - nouveau_bo_ref(NULL, &buffer->bo); - free(buffer); + nouveau_bo_ref(NULL, &buffer->bo); + free(buffer); } - |