Home | History | Annotate | Download | only in nv30
      1 /*
      2  * Copyright 2012 Red Hat Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20  * OTHER DEALINGS IN THE SOFTWARE.
     21  *
     22  * Authors: Ben Skeggs
     23  *
     24  */
     25 
     26 #include "pipe/p_defines.h"
     27 #include "util/u_pack_color.h"
     28 
     29 #include "nouveau_gldefs.h"
     30 #include "nv_object.xml.h"
     31 #include "nv30/nv30-40_3d.xml.h"
     32 #include "nv30/nv30_context.h"
     33 #include "nv30/nv30_format.h"
     34 
     35 static inline uint32_t
     36 pack_rgba(enum pipe_format format, const float *rgba)
     37 {
     38    union util_color uc;
     39    util_pack_color(rgba, format, &uc);
     40    return uc.ui[0];
     41 }
     42 
     43 static inline uint32_t
     44 pack_zeta(enum pipe_format format, double depth, unsigned stencil)
     45 {
     46    uint32_t zuint = (uint32_t)(depth * 4294967295.0);
     47    if (format != PIPE_FORMAT_Z16_UNORM)
     48       return (zuint & 0xffffff00) | (stencil & 0xff);
     49    return zuint >> 16;
     50 }
     51 
     52 static void
     53 nv30_clear(struct pipe_context *pipe, unsigned buffers,
     54            const union pipe_color_union *color, double depth, unsigned stencil)
     55 {
     56    struct nv30_context *nv30 = nv30_context(pipe);
     57    struct nouveau_pushbuf *push = nv30->base.pushbuf;
     58    struct pipe_framebuffer_state *fb = &nv30->framebuffer;
     59    uint32_t colr = 0, zeta = 0, mode = 0;
     60 
     61    if (!nv30_state_validate(nv30, NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR, true))
     62       return;
     63 
     64    if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
     65       colr  = pack_rgba(fb->cbufs[0]->format, color->f);
     66       mode |= NV30_3D_CLEAR_BUFFERS_COLOR_R |
     67               NV30_3D_CLEAR_BUFFERS_COLOR_G |
     68               NV30_3D_CLEAR_BUFFERS_COLOR_B |
     69               NV30_3D_CLEAR_BUFFERS_COLOR_A;
     70    }
     71 
     72    if (fb->zsbuf) {
     73       zeta = pack_zeta(fb->zsbuf->format, depth, stencil);
     74       if (buffers & PIPE_CLEAR_DEPTH)
     75          mode |= NV30_3D_CLEAR_BUFFERS_DEPTH;
     76       if (buffers & PIPE_CLEAR_STENCIL) {
     77          mode |= NV30_3D_CLEAR_BUFFERS_STENCIL;
     78          BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(0)), 2);
     79          PUSH_DATA (push, 0);
     80          PUSH_DATA (push, 0x000000ff);
     81          nv30->dirty |= NV30_NEW_ZSA;
     82       }
     83    }
     84 
     85    /*XXX: wtf? fixes clears sometimes not clearing on nv3x... */
     86    if (nv30->screen->eng3d->oclass < NV40_3D_CLASS) {
     87       BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3);
     88       PUSH_DATA (push, zeta);
     89       PUSH_DATA (push, colr);
     90       PUSH_DATA (push, mode);
     91    }
     92 
     93    BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3);
     94    PUSH_DATA (push, zeta);
     95    PUSH_DATA (push, colr);
     96    PUSH_DATA (push, mode);
     97 
     98    nv30_state_release(nv30);
     99 }
    100 
    101 static void
    102 nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps,
    103                          const union pipe_color_union *color,
    104                          unsigned x, unsigned y, unsigned w, unsigned h,
    105                          bool render_condition_enabled)
    106 {
    107    struct nv30_context *nv30 = nv30_context(pipe);
    108    struct nv30_surface *sf = nv30_surface(ps);
    109    struct nv30_miptree *mt = nv30_miptree(ps->texture);
    110    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    111    struct nouveau_object *eng3d = nv30->screen->eng3d;
    112    struct nouveau_pushbuf_refn refn;
    113    uint32_t rt_format;
    114 
    115    rt_format = nv30_format(pipe->screen, ps->format)->hw;
    116    if (util_format_get_blocksize(ps->format) == 4)
    117       rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8;
    118    else
    119       rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16;
    120 
    121    if (nv30_miptree(ps->texture)->swizzled) {
    122       rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
    123       rt_format |= util_logbase2(sf->width) << 16;
    124       rt_format |= util_logbase2(sf->height) << 24;
    125    } else {
    126       rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
    127    }
    128 
    129    refn.bo = mt->base.bo;
    130    refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR;
    131    if (nouveau_pushbuf_space(push, 32, 1, 0) ||
    132        nouveau_pushbuf_refn (push, &refn, 1))
    133       return;
    134 
    135    BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
    136    PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0);
    137    BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
    138    PUSH_DATA (push, sf->width << 16);
    139    PUSH_DATA (push, sf->height << 16);
    140    PUSH_DATA (push, rt_format);
    141    BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 2);
    142    if (eng3d->oclass < NV40_3D_CLASS)
    143       PUSH_DATA (push, (sf->pitch << 16) | sf->pitch);
    144    else
    145       PUSH_DATA (push, sf->pitch);
    146    PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0);
    147    BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
    148    PUSH_DATA (push, (w << 16) | x);
    149    PUSH_DATA (push, (h << 16) | y);
    150 
    151    BEGIN_NV04(push, NV30_3D(CLEAR_COLOR_VALUE), 2);
    152    PUSH_DATA (push, pack_rgba(ps->format, color->f));
    153    PUSH_DATA (push, NV30_3D_CLEAR_BUFFERS_COLOR_R |
    154                     NV30_3D_CLEAR_BUFFERS_COLOR_G |
    155                     NV30_3D_CLEAR_BUFFERS_COLOR_B |
    156                     NV30_3D_CLEAR_BUFFERS_COLOR_A);
    157 
    158    nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR;
    159 }
    160 
    161 static void
    162 nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps,
    163                          unsigned buffers, double depth, unsigned stencil,
    164                          unsigned x, unsigned y, unsigned w, unsigned h,
    165                          bool render_condition_enabled)
    166 {
    167    struct nv30_context *nv30 = nv30_context(pipe);
    168    struct nv30_surface *sf = nv30_surface(ps);
    169    struct nv30_miptree *mt = nv30_miptree(ps->texture);
    170    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    171    struct nouveau_object *eng3d = nv30->screen->eng3d;
    172    struct nouveau_pushbuf_refn refn;
    173    uint32_t rt_format, mode = 0;
    174 
    175    rt_format = nv30_format(pipe->screen, ps->format)->hw;
    176    if (util_format_get_blocksize(ps->format) == 4)
    177       rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8;
    178    else
    179       rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5;
    180 
    181    if (nv30_miptree(ps->texture)->swizzled) {
    182       rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
    183       rt_format |= util_logbase2(sf->width) << 16;
    184       rt_format |= util_logbase2(sf->height) << 24;
    185    } else {
    186       rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
    187    }
    188 
    189    if (buffers & PIPE_CLEAR_DEPTH)
    190       mode |= NV30_3D_CLEAR_BUFFERS_DEPTH;
    191    if (buffers & PIPE_CLEAR_STENCIL)
    192       mode |= NV30_3D_CLEAR_BUFFERS_STENCIL;
    193 
    194    refn.bo = mt->base.bo;
    195    refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR;
    196    if (nouveau_pushbuf_space(push, 32, 1, 0) ||
    197        nouveau_pushbuf_refn (push, &refn, 1))
    198       return;
    199 
    200    BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
    201    PUSH_DATA (push, 0);
    202    BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
    203    PUSH_DATA (push, sf->width << 16);
    204    PUSH_DATA (push, sf->height << 16);
    205    PUSH_DATA (push, rt_format);
    206    if (eng3d->oclass < NV40_3D_CLASS) {
    207       BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 1);
    208       PUSH_DATA (push, (sf->pitch << 16) | sf->pitch);
    209    } else {
    210       BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1);
    211       PUSH_DATA (push, sf->pitch);
    212    }
    213    BEGIN_NV04(push, NV30_3D(ZETA_OFFSET), 1);
    214    PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0);
    215    BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
    216    PUSH_DATA (push, (w << 16) | x);
    217    PUSH_DATA (push, (h << 16) | y);
    218 
    219    BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 1);
    220    PUSH_DATA (push, pack_zeta(ps->format, depth, stencil));
    221    BEGIN_NV04(push, NV30_3D(CLEAR_BUFFERS), 1);
    222    PUSH_DATA (push, mode);
    223 
    224    nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR;
    225 }
    226 
    227 void
    228 nv30_clear_init(struct pipe_context *pipe)
    229 {
    230    pipe->clear = nv30_clear;
    231    pipe->clear_render_target = nv30_clear_render_target;
    232    pipe->clear_depth_stencil = nv30_clear_depth_stencil;
    233 }
    234