612 lines
18 KiB
C
612 lines
18 KiB
C
/*
|
|
* Copyright (C) 2007-2010 The Nouveau Project.
|
|
* All Rights Reserved.
|
|
*
|
|
* 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "nouveau_driver.h"
|
|
#include "nv_object.xml.h"
|
|
#include "nv_m2mf.xml.h"
|
|
#include "nv01_2d.xml.h"
|
|
#include "nv04_3d.xml.h"
|
|
#include "nouveau_context.h"
|
|
#include "nouveau_util.h"
|
|
#include "nv04_driver.h"
|
|
|
|
static inline int
|
|
swzsurf_format(mesa_format format)
|
|
{
|
|
switch (format) {
|
|
case MESA_FORMAT_A_UNORM8:
|
|
case MESA_FORMAT_L_UNORM8:
|
|
case MESA_FORMAT_I_UNORM8:
|
|
case MESA_FORMAT_B2G3R3_UNORM:
|
|
return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y8;
|
|
|
|
case MESA_FORMAT_B5G6R5_UNORM:
|
|
case MESA_FORMAT_R5G6B5_UNORM:
|
|
case MESA_FORMAT_B4G4R4A4_UNORM:
|
|
case MESA_FORMAT_A4R4G4B4_UNORM:
|
|
case MESA_FORMAT_B5G5R5A1_UNORM:
|
|
case MESA_FORMAT_A1B5G5R5_UNORM:
|
|
case MESA_FORMAT_A1R5G5B5_UNORM:
|
|
case MESA_FORMAT_LA_UNORM8:
|
|
case MESA_FORMAT_YCBCR:
|
|
case MESA_FORMAT_YCBCR_REV:
|
|
case MESA_FORMAT_Z_UNORM16:
|
|
return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_R5G6B5;
|
|
|
|
case MESA_FORMAT_A8B8G8R8_UNORM:
|
|
case MESA_FORMAT_R8G8B8A8_UNORM:
|
|
case MESA_FORMAT_B8G8R8X8_UNORM:
|
|
case MESA_FORMAT_B8G8R8A8_UNORM:
|
|
case MESA_FORMAT_A8R8G8B8_UNORM:
|
|
case MESA_FORMAT_Z24_UNORM_S8_UINT:
|
|
case MESA_FORMAT_S8_UINT_Z24_UNORM:
|
|
case MESA_FORMAT_Z_UNORM32:
|
|
return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
static inline int
|
|
surf2d_format(mesa_format format)
|
|
{
|
|
switch (format) {
|
|
case MESA_FORMAT_A_UNORM8:
|
|
case MESA_FORMAT_L_UNORM8:
|
|
case MESA_FORMAT_I_UNORM8:
|
|
case MESA_FORMAT_B2G3R3_UNORM:
|
|
return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
|
|
|
|
case MESA_FORMAT_B5G6R5_UNORM:
|
|
case MESA_FORMAT_R5G6B5_UNORM:
|
|
case MESA_FORMAT_B4G4R4A4_UNORM:
|
|
case MESA_FORMAT_A4R4G4B4_UNORM:
|
|
case MESA_FORMAT_B5G5R5A1_UNORM:
|
|
case MESA_FORMAT_A1B5G5R5_UNORM:
|
|
case MESA_FORMAT_A1R5G5B5_UNORM:
|
|
case MESA_FORMAT_LA_UNORM8:
|
|
case MESA_FORMAT_YCBCR:
|
|
case MESA_FORMAT_YCBCR_REV:
|
|
case MESA_FORMAT_Z_UNORM16:
|
|
return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
|
|
|
|
case MESA_FORMAT_A8B8G8R8_UNORM:
|
|
case MESA_FORMAT_R8G8B8A8_UNORM:
|
|
case MESA_FORMAT_B8G8R8X8_UNORM:
|
|
case MESA_FORMAT_B8G8R8A8_UNORM:
|
|
case MESA_FORMAT_A8R8G8B8_UNORM:
|
|
case MESA_FORMAT_Z24_UNORM_S8_UINT:
|
|
case MESA_FORMAT_S8_UINT_Z24_UNORM:
|
|
case MESA_FORMAT_Z_UNORM32:
|
|
return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
static inline int
|
|
rect_format(mesa_format format)
|
|
{
|
|
switch (format) {
|
|
case MESA_FORMAT_A_UNORM8:
|
|
case MESA_FORMAT_L_UNORM8:
|
|
case MESA_FORMAT_I_UNORM8:
|
|
case MESA_FORMAT_B2G3R3_UNORM:
|
|
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
|
|
|
|
case MESA_FORMAT_B5G6R5_UNORM:
|
|
case MESA_FORMAT_R5G6B5_UNORM:
|
|
case MESA_FORMAT_B4G4R4A4_UNORM:
|
|
case MESA_FORMAT_A4R4G4B4_UNORM:
|
|
case MESA_FORMAT_B5G5R5A1_UNORM:
|
|
case MESA_FORMAT_A1B5G5R5_UNORM:
|
|
case MESA_FORMAT_A1R5G5B5_UNORM:
|
|
case MESA_FORMAT_LA_UNORM8:
|
|
case MESA_FORMAT_YCBCR:
|
|
case MESA_FORMAT_YCBCR_REV:
|
|
case MESA_FORMAT_Z_UNORM16:
|
|
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
|
|
|
|
case MESA_FORMAT_A8B8G8R8_UNORM:
|
|
case MESA_FORMAT_R8G8B8A8_UNORM:
|
|
case MESA_FORMAT_B8G8R8X8_UNORM:
|
|
case MESA_FORMAT_B8G8R8A8_UNORM:
|
|
case MESA_FORMAT_A8R8G8B8_UNORM:
|
|
case MESA_FORMAT_Z24_UNORM_S8_UINT:
|
|
case MESA_FORMAT_S8_UINT_Z24_UNORM:
|
|
case MESA_FORMAT_Z_UNORM32:
|
|
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
static inline int
|
|
sifm_format(mesa_format format)
|
|
{
|
|
switch (format) {
|
|
case MESA_FORMAT_A_UNORM8:
|
|
case MESA_FORMAT_L_UNORM8:
|
|
case MESA_FORMAT_I_UNORM8:
|
|
case MESA_FORMAT_B2G3R3_UNORM:
|
|
return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8;
|
|
|
|
case MESA_FORMAT_B5G6R5_UNORM:
|
|
case MESA_FORMAT_R5G6B5_UNORM:
|
|
case MESA_FORMAT_B4G4R4A4_UNORM:
|
|
case MESA_FORMAT_A4R4G4B4_UNORM:
|
|
case MESA_FORMAT_B5G5R5A1_UNORM:
|
|
case MESA_FORMAT_A1B5G5R5_UNORM:
|
|
case MESA_FORMAT_A1R5G5B5_UNORM:
|
|
case MESA_FORMAT_LA_UNORM8:
|
|
case MESA_FORMAT_YCBCR:
|
|
case MESA_FORMAT_YCBCR_REV:
|
|
case MESA_FORMAT_Z_UNORM16:
|
|
return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
|
|
|
|
case MESA_FORMAT_A8B8G8R8_UNORM:
|
|
case MESA_FORMAT_R8G8B8A8_UNORM:
|
|
case MESA_FORMAT_B8G8R8X8_UNORM:
|
|
case MESA_FORMAT_B8G8R8A8_UNORM:
|
|
case MESA_FORMAT_A8R8G8B8_UNORM:
|
|
case MESA_FORMAT_Z24_UNORM_S8_UINT:
|
|
case MESA_FORMAT_S8_UINT_Z24_UNORM:
|
|
case MESA_FORMAT_Z_UNORM32:
|
|
return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
nv04_surface_copy_swizzle(struct gl_context *ctx,
|
|
struct nouveau_surface *dst,
|
|
struct nouveau_surface *src,
|
|
int dx, int dy, int sx, int sy,
|
|
int w, int h)
|
|
{
|
|
struct nouveau_pushbuf_refn refs[] = {
|
|
{ src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
|
|
{ dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM },
|
|
};
|
|
struct nouveau_pushbuf *push = context_push(ctx);
|
|
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
|
|
struct nouveau_object *swzsurf = hw->swzsurf;
|
|
struct nv04_fifo *fifo = hw->chan->data;
|
|
/* Max width & height may not be the same on all HW, but must be POT */
|
|
const unsigned max_w = 1024;
|
|
const unsigned max_h = 1024;
|
|
unsigned sub_w = w > max_w ? max_w : w;
|
|
unsigned sub_h = h > max_h ? max_h : h;
|
|
unsigned x, y;
|
|
|
|
/* Swizzled surfaces must be POT */
|
|
assert(util_is_power_of_two_or_zero(dst->width) &&
|
|
util_is_power_of_two_or_zero(dst->height));
|
|
|
|
if (context_chipset(ctx) < 0x10) {
|
|
BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
|
|
PUSH_DATA (push, swzsurf->handle);
|
|
}
|
|
|
|
for (y = 0; y < h; y += sub_h) {
|
|
sub_h = MIN2(sub_h, h - y);
|
|
|
|
for (x = 0; x < w; x += sub_w) {
|
|
sub_w = MIN2(sub_w, w - x);
|
|
|
|
if (nouveau_pushbuf_space(push, 64, 4, 0) ||
|
|
nouveau_pushbuf_refn (push, refs, 2))
|
|
return;
|
|
|
|
BEGIN_NV04(push, NV04_SSWZ(DMA_IMAGE), 1);
|
|
PUSH_DATA (push, fifo->vram);
|
|
BEGIN_NV04(push, NV04_SSWZ(FORMAT), 2);
|
|
PUSH_DATA (push, swzsurf_format(dst->format) |
|
|
log2i(dst->width) << 16 |
|
|
log2i(dst->height) << 24);
|
|
PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
|
|
|
|
BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1);
|
|
PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
|
|
BEGIN_NV04(push, NV05_SIFM(SURFACE), 1);
|
|
PUSH_DATA (push, swzsurf->handle);
|
|
|
|
BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 8);
|
|
PUSH_DATA (push, sifm_format(src->format));
|
|
PUSH_DATA (push, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
|
|
PUSH_DATA (push, (y + dy) << 16 | (x + dx));
|
|
PUSH_DATA (push, sub_h << 16 | sub_w);
|
|
PUSH_DATA (push, (y + dy) << 16 | (x + dx));
|
|
PUSH_DATA (push, sub_h << 16 | sub_w);
|
|
PUSH_DATA (push, 1 << 20);
|
|
PUSH_DATA (push, 1 << 20);
|
|
|
|
BEGIN_NV04(push, NV03_SIFM(SIZE), 4);
|
|
PUSH_DATA (push, align(sub_h, 2) << 16 | align(sub_w, 2));
|
|
PUSH_DATA (push, src->pitch |
|
|
NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
|
|
NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
|
|
PUSH_RELOC(push, src->bo, src->offset + (y + sy) * src->pitch +
|
|
(x + sx) * src->cpp, NOUVEAU_BO_LOW, 0, 0);
|
|
PUSH_DATA (push, 0);
|
|
}
|
|
}
|
|
|
|
if (context_chipset(ctx) < 0x10) {
|
|
BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
|
|
PUSH_DATA (push, hw->surf3d->handle);
|
|
}
|
|
}
|
|
|
|
static void
|
|
nv04_surface_copy_m2mf(struct gl_context *ctx,
|
|
struct nouveau_surface *dst,
|
|
struct nouveau_surface *src,
|
|
int dx, int dy, int sx, int sy,
|
|
int w, int h)
|
|
{
|
|
struct nouveau_pushbuf_refn refs[] = {
|
|
{ src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
|
|
{ dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
|
|
};
|
|
struct nouveau_pushbuf *push = context_push(ctx);
|
|
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
|
|
struct nv04_fifo *fifo = hw->chan->data;
|
|
unsigned dst_offset = dst->offset + dy * dst->pitch + dx * dst->cpp;
|
|
unsigned src_offset = src->offset + sy * src->pitch + sx * src->cpp;
|
|
|
|
while (h) {
|
|
int count = (h > 2047) ? 2047 : h;
|
|
|
|
if (nouveau_pushbuf_space(push, 16, 4, 0) ||
|
|
nouveau_pushbuf_refn (push, refs, 2))
|
|
return;
|
|
|
|
BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);
|
|
PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
|
|
PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
|
|
BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
|
|
PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0);
|
|
PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
|
|
PUSH_DATA (push, src->pitch);
|
|
PUSH_DATA (push, dst->pitch);
|
|
PUSH_DATA (push, w * src->cpp);
|
|
PUSH_DATA (push, count);
|
|
PUSH_DATA (push, 0x0101);
|
|
PUSH_DATA (push, 0);
|
|
|
|
src_offset += src->pitch * count;
|
|
dst_offset += dst->pitch * count;
|
|
h -= count;
|
|
}
|
|
}
|
|
|
|
typedef unsigned (*get_offset_t)(struct nouveau_surface *s,
|
|
unsigned x, unsigned y);
|
|
|
|
static unsigned
|
|
get_linear_offset(struct nouveau_surface *s, unsigned x, unsigned y)
|
|
{
|
|
return x * s->cpp + y * s->pitch;
|
|
}
|
|
|
|
static unsigned
|
|
get_swizzled_offset(struct nouveau_surface *s, unsigned x, unsigned y)
|
|
{
|
|
unsigned k = log2i(MIN2(s->width, s->height));
|
|
|
|
unsigned u = (x & 0x001) << 0 |
|
|
(x & 0x002) << 1 |
|
|
(x & 0x004) << 2 |
|
|
(x & 0x008) << 3 |
|
|
(x & 0x010) << 4 |
|
|
(x & 0x020) << 5 |
|
|
(x & 0x040) << 6 |
|
|
(x & 0x080) << 7 |
|
|
(x & 0x100) << 8 |
|
|
(x & 0x200) << 9 |
|
|
(x & 0x400) << 10 |
|
|
(x & 0x800) << 11;
|
|
|
|
unsigned v = (y & 0x001) << 1 |
|
|
(y & 0x002) << 2 |
|
|
(y & 0x004) << 3 |
|
|
(y & 0x008) << 4 |
|
|
(y & 0x010) << 5 |
|
|
(y & 0x020) << 6 |
|
|
(y & 0x040) << 7 |
|
|
(y & 0x080) << 8 |
|
|
(y & 0x100) << 9 |
|
|
(y & 0x200) << 10 |
|
|
(y & 0x400) << 11 |
|
|
(y & 0x800) << 12;
|
|
|
|
return s->cpp * (((u | v) & ~(~0 << 2*k)) |
|
|
(x & (~0 << k)) << k |
|
|
(y & (~0 << k)) << k);
|
|
}
|
|
|
|
static void
|
|
nv04_surface_copy_cpu(struct gl_context *ctx,
|
|
struct nouveau_surface *dst,
|
|
struct nouveau_surface *src,
|
|
int dx, int dy, int sx, int sy,
|
|
int w, int h)
|
|
{
|
|
int x, y;
|
|
get_offset_t get_dst = (dst->layout == SWIZZLED ?
|
|
get_swizzled_offset : get_linear_offset);
|
|
get_offset_t get_src = (src->layout == SWIZZLED ?
|
|
get_swizzled_offset : get_linear_offset);
|
|
void *dp, *sp;
|
|
|
|
nouveau_bo_map(dst->bo, NOUVEAU_BO_WR, context_client(ctx));
|
|
nouveau_bo_map(src->bo, NOUVEAU_BO_RD, context_client(ctx));
|
|
|
|
dp = dst->bo->map + dst->offset;
|
|
sp = src->bo->map + src->offset;
|
|
|
|
for (y = 0; y < h; y++) {
|
|
for (x = 0; x < w; x++) {
|
|
memcpy(dp + get_dst(dst, dx + x, dy + y),
|
|
sp + get_src(src, sx + x, sy + y), dst->cpp);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
nv04_surface_copy(struct gl_context *ctx,
|
|
struct nouveau_surface *dst,
|
|
struct nouveau_surface *src,
|
|
int dx, int dy, int sx, int sy,
|
|
int w, int h)
|
|
{
|
|
if (_mesa_is_format_compressed(src->format)) {
|
|
sx = get_format_blocksx(src->format, sx);
|
|
sy = get_format_blocksy(src->format, sy);
|
|
dx = get_format_blocksx(dst->format, dx);
|
|
dy = get_format_blocksy(dst->format, dy);
|
|
w = get_format_blocksx(src->format, w);
|
|
h = get_format_blocksy(src->format, h);
|
|
}
|
|
|
|
/* Linear texture copy. */
|
|
if ((src->layout == LINEAR && dst->layout == LINEAR) ||
|
|
dst->width <= 2 || dst->height <= 1) {
|
|
nv04_surface_copy_m2mf(ctx, dst, src, dx, dy, sx, sy, w, h);
|
|
return;
|
|
}
|
|
|
|
/* Swizzle using sifm+swzsurf. */
|
|
if (src->layout == LINEAR && dst->layout == SWIZZLED &&
|
|
dst->cpp != 1 && !(dst->offset & 63)) {
|
|
nv04_surface_copy_swizzle(ctx, dst, src, dx, dy, sx, sy, w, h);
|
|
return;
|
|
}
|
|
|
|
/* Fallback to CPU copy. */
|
|
nv04_surface_copy_cpu(ctx, dst, src, dx, dy, sx, sy, w, h);
|
|
}
|
|
|
|
void
|
|
nv04_surface_fill(struct gl_context *ctx,
|
|
struct nouveau_surface *dst,
|
|
unsigned mask, unsigned value,
|
|
int dx, int dy, int w, int h)
|
|
{
|
|
struct nouveau_pushbuf_refn refs[] = {
|
|
{ dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
|
|
};
|
|
struct nouveau_pushbuf *push = context_push(ctx);
|
|
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
|
|
struct nv04_fifo *fifo = hw->chan->data;
|
|
|
|
if (nouveau_pushbuf_space(push, 64, 4, 0) ||
|
|
nouveau_pushbuf_refn (push, refs, 1))
|
|
return;
|
|
|
|
BEGIN_NV04(push, NV04_SF2D(DMA_IMAGE_SOURCE), 2);
|
|
PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
|
|
PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
|
|
BEGIN_NV04(push, NV04_SF2D(FORMAT), 4);
|
|
PUSH_DATA (push, surf2d_format(dst->format));
|
|
PUSH_DATA (push, (dst->pitch << 16) | dst->pitch);
|
|
PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
|
|
PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
|
|
|
|
BEGIN_NV04(push, NV01_PATT(COLOR_FORMAT), 1);
|
|
PUSH_DATA (push, rect_format(dst->format));
|
|
BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR1), 1);
|
|
PUSH_DATA (push, mask | ~0ll << (8 * dst->cpp));
|
|
|
|
BEGIN_NV04(push, NV04_GDI(COLOR_FORMAT), 1);
|
|
PUSH_DATA (push, rect_format(dst->format));
|
|
BEGIN_NV04(push, NV04_GDI(COLOR1_A), 1);
|
|
PUSH_DATA (push, value);
|
|
BEGIN_NV04(push, NV04_GDI(UNCLIPPED_RECTANGLE_POINT(0)), 2);
|
|
PUSH_DATA (push, (dx << 16) | dy);
|
|
PUSH_DATA (push, ( w << 16) | h);
|
|
}
|
|
|
|
void
|
|
nv04_surface_takedown(struct gl_context *ctx)
|
|
{
|
|
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
|
|
|
|
nouveau_object_del(&hw->swzsurf);
|
|
nouveau_object_del(&hw->sifm);
|
|
nouveau_object_del(&hw->rect);
|
|
nouveau_object_del(&hw->rop);
|
|
nouveau_object_del(&hw->patt);
|
|
nouveau_object_del(&hw->surf2d);
|
|
nouveau_object_del(&hw->m2mf);
|
|
nouveau_object_del(&hw->ntfy);
|
|
}
|
|
|
|
GLboolean
|
|
nv04_surface_init(struct gl_context *ctx)
|
|
{
|
|
struct nouveau_pushbuf *push = context_push(ctx);
|
|
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
|
|
struct nouveau_object *chan = hw->chan;
|
|
unsigned handle = 0x88000000, class;
|
|
int ret;
|
|
|
|
/* Notifier object. */
|
|
ret = nouveau_object_new(chan, handle++, NOUVEAU_NOTIFIER_CLASS,
|
|
&(struct nv04_notify) {
|
|
.length = 32,
|
|
}, sizeof(struct nv04_notify), &hw->ntfy);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
/* Memory to memory format. */
|
|
ret = nouveau_object_new(chan, handle++, NV03_M2MF_CLASS,
|
|
NULL, 0, &hw->m2mf);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
BEGIN_NV04(push, NV01_SUBC(M2MF, OBJECT), 1);
|
|
PUSH_DATA (push, hw->m2mf->handle);
|
|
BEGIN_NV04(push, NV03_M2MF(DMA_NOTIFY), 1);
|
|
PUSH_DATA (push, hw->ntfy->handle);
|
|
|
|
/* Context surfaces 2D. */
|
|
if (context_chipset(ctx) < 0x10)
|
|
class = NV04_SURFACE_2D_CLASS;
|
|
else
|
|
class = NV10_SURFACE_2D_CLASS;
|
|
|
|
ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->surf2d);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
BEGIN_NV04(push, NV01_SUBC(SF2D, OBJECT), 1);
|
|
PUSH_DATA (push, hw->surf2d->handle);
|
|
|
|
/* Raster op. */
|
|
ret = nouveau_object_new(chan, handle++, NV03_ROP_CLASS,
|
|
NULL, 0, &hw->rop);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
BEGIN_NV04(push, NV01_SUBC(PATT, OBJECT), 1);
|
|
PUSH_DATA (push, hw->rop->handle);
|
|
BEGIN_NV04(push, NV01_ROP(DMA_NOTIFY), 1);
|
|
PUSH_DATA (push, hw->ntfy->handle);
|
|
|
|
BEGIN_NV04(push, NV01_ROP(ROP), 1);
|
|
PUSH_DATA (push, 0xca); /* DPSDxax in the GDI speech. */
|
|
|
|
/* Image pattern. */
|
|
ret = nouveau_object_new(chan, handle++, NV04_PATTERN_CLASS,
|
|
NULL, 0, &hw->patt);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
BEGIN_NV04(push, NV01_SUBC(PATT, OBJECT), 1);
|
|
PUSH_DATA (push, hw->patt->handle);
|
|
BEGIN_NV04(push, NV01_PATT(DMA_NOTIFY), 1);
|
|
PUSH_DATA (push, hw->ntfy->handle);
|
|
|
|
BEGIN_NV04(push, NV01_PATT(MONOCHROME_FORMAT), 3);
|
|
PUSH_DATA (push, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE);
|
|
PUSH_DATA (push, NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8);
|
|
PUSH_DATA (push, NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO);
|
|
|
|
BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR0), 4);
|
|
PUSH_DATA (push, 0);
|
|
PUSH_DATA (push, 0);
|
|
PUSH_DATA (push, ~0);
|
|
PUSH_DATA (push, ~0);
|
|
|
|
/* GDI rectangle text. */
|
|
ret = nouveau_object_new(chan, handle++, NV04_GDI_CLASS,
|
|
NULL, 0, &hw->rect);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
BEGIN_NV04(push, NV01_SUBC(GDI, OBJECT), 1);
|
|
PUSH_DATA (push, hw->rect->handle);
|
|
BEGIN_NV04(push, NV04_GDI(DMA_NOTIFY), 1);
|
|
PUSH_DATA (push, hw->ntfy->handle);
|
|
BEGIN_NV04(push, NV04_GDI(SURFACE), 1);
|
|
PUSH_DATA (push, hw->surf2d->handle);
|
|
BEGIN_NV04(push, NV04_GDI(ROP), 1);
|
|
PUSH_DATA (push, hw->rop->handle);
|
|
BEGIN_NV04(push, NV04_GDI(PATTERN), 1);
|
|
PUSH_DATA (push, hw->patt->handle);
|
|
|
|
BEGIN_NV04(push, NV04_GDI(OPERATION), 1);
|
|
PUSH_DATA (push, NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND);
|
|
BEGIN_NV04(push, NV04_GDI(MONOCHROME_FORMAT), 1);
|
|
PUSH_DATA (push, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
|
|
|
|
/* Swizzled surface. */
|
|
if (context_chipset(ctx) < 0x20)
|
|
class = NV04_SURFACE_SWZ_CLASS;
|
|
else if (context_chipset (ctx) < 0x30)
|
|
class = NV20_SURFACE_SWZ_CLASS;
|
|
else
|
|
class = NV30_SURFACE_SWZ_CLASS;
|
|
|
|
ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->swzsurf);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
|
|
PUSH_DATA (push, hw->swzsurf->handle);
|
|
|
|
/* Scaled image from memory. */
|
|
if (context_chipset(ctx) < 0x10)
|
|
class = NV04_SIFM_CLASS;
|
|
else
|
|
class = NV10_SIFM_CLASS;
|
|
|
|
ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->sifm);
|
|
if (ret)
|
|
goto fail;
|
|
|
|
BEGIN_NV04(push, NV01_SUBC(SIFM, OBJECT), 1);
|
|
PUSH_DATA (push, hw->sifm->handle);
|
|
|
|
if (context_chipset(ctx) >= 0x10) {
|
|
BEGIN_NV04(push, NV05_SIFM(COLOR_CONVERSION), 1);
|
|
PUSH_DATA (push, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
|
|
}
|
|
|
|
return GL_TRUE;
|
|
|
|
fail:
|
|
nv04_surface_takedown(ctx);
|
|
return GL_FALSE;
|
|
}
|