2 * Copyright (c) 2012-2015 Etnaviv Project
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, sub license,
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:
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 * Wladimir J. van der Laan <laanwj@gmail.com>
27 #include "etnaviv_rs.h"
28 #include "etnaviv_screen.h"
29 #include "etnaviv_tiling.h"
30 #include "etnaviv_util.h"
32 #include "hw/common.xml.h"
33 #include "hw/state.xml.h"
34 #include "hw/state_3d.xml.h"
39 etna_compile_rs_state(struct etna_context
*ctx
, struct compiled_rs_state
*cs
,
40 const struct rs_state
*rs
)
42 memset(cs
, 0, sizeof(*cs
));
44 /* TILED and SUPERTILED layout have their strides multiplied with 4 in RS */
45 unsigned source_stride_shift
= COND(rs
->source_tiling
!= ETNA_LAYOUT_LINEAR
, 2);
46 unsigned dest_stride_shift
= COND(rs
->dest_tiling
!= ETNA_LAYOUT_LINEAR
, 2);
48 /* tiling == ETNA_LAYOUT_MULTI_TILED or ETNA_LAYOUT_MULTI_SUPERTILED? */
49 int source_multi
= COND(rs
->source_tiling
& ETNA_LAYOUT_BIT_MULTI
, 1);
50 int dest_multi
= COND(rs
->dest_tiling
& ETNA_LAYOUT_BIT_MULTI
, 1);
52 /* Vivante RS needs widths to be a multiple of 16 or bad things
53 * happen, such as scribbing over memory, or the GPU hanging,
54 * even for non-tiled formats. As this is serious, use abort().
56 if (rs
->width
& ETNA_RS_WIDTH_MASK
)
59 /* TODO could just pre-generate command buffer, would simply submit to one memcpy */
60 cs
->RS_CONFIG
= VIVS_RS_CONFIG_SOURCE_FORMAT(rs
->source_format
) |
61 COND(rs
->downsample_x
, VIVS_RS_CONFIG_DOWNSAMPLE_X
) |
62 COND(rs
->downsample_y
, VIVS_RS_CONFIG_DOWNSAMPLE_Y
) |
63 COND(rs
->source_tiling
& 1, VIVS_RS_CONFIG_SOURCE_TILED
) |
64 VIVS_RS_CONFIG_DEST_FORMAT(rs
->dest_format
) |
65 COND(rs
->dest_tiling
& 1, VIVS_RS_CONFIG_DEST_TILED
) |
66 COND(rs
->swap_rb
, VIVS_RS_CONFIG_SWAP_RB
) |
67 COND(rs
->flip
, VIVS_RS_CONFIG_FLIP
);
69 cs
->RS_SOURCE_STRIDE
= (rs
->source_stride
<< source_stride_shift
) |
70 COND(rs
->source_tiling
& 2, VIVS_RS_SOURCE_STRIDE_TILING
) |
71 COND(source_multi
, VIVS_RS_SOURCE_STRIDE_MULTI
);
73 /* Initially all pipes are set to the base address of the source and
74 * destination buffer respectively. This will be overridden below as
75 * necessary for the multi-pipe, multi-tiled case.
77 for (unsigned pipe
= 0; pipe
< ctx
->specs
.pixel_pipes
; ++pipe
) {
78 cs
->source
[pipe
].bo
= rs
->source
;
79 cs
->source
[pipe
].offset
= rs
->source_offset
;
80 cs
->source
[pipe
].flags
= ETNA_RELOC_READ
;
82 cs
->dest
[pipe
].bo
= rs
->dest
;
83 cs
->dest
[pipe
].offset
= rs
->dest_offset
;
84 cs
->dest
[pipe
].flags
= ETNA_RELOC_WRITE
;
86 cs
->RS_PIPE_OFFSET
[pipe
] = VIVS_RS_PIPE_OFFSET_X(0) | VIVS_RS_PIPE_OFFSET_Y(0);
89 cs
->RS_DEST_STRIDE
= (rs
->dest_stride
<< dest_stride_shift
) |
90 COND(rs
->dest_tiling
& 2, VIVS_RS_DEST_STRIDE_TILING
) |
91 COND(dest_multi
, VIVS_RS_DEST_STRIDE_MULTI
);
93 if (ctx
->specs
.pixel_pipes
== 1 || ctx
->specs
.single_buffer
) {
94 cs
->RS_WINDOW_SIZE
= VIVS_RS_WINDOW_SIZE_WIDTH(rs
->width
) |
95 VIVS_RS_WINDOW_SIZE_HEIGHT(rs
->height
);
96 } else if (ctx
->specs
.pixel_pipes
== 2) {
97 assert((rs
->height
& 7) == 0); /* GPU hangs happen if height not 8-aligned */
100 cs
->source
[1].offset
= rs
->source_offset
+ rs
->source_stride
* rs
->source_padded_height
/ 2;
103 cs
->dest
[1].offset
= rs
->dest_offset
+ rs
->dest_stride
* rs
->dest_padded_height
/ 2;
105 cs
->RS_WINDOW_SIZE
= VIVS_RS_WINDOW_SIZE_WIDTH(rs
->width
) |
106 VIVS_RS_WINDOW_SIZE_HEIGHT(rs
->height
/ 2);
107 cs
->RS_PIPE_OFFSET
[1] = VIVS_RS_PIPE_OFFSET_X(0) | VIVS_RS_PIPE_OFFSET_Y(rs
->height
/ 2);
112 cs
->RS_DITHER
[0] = rs
->dither
[0];
113 cs
->RS_DITHER
[1] = rs
->dither
[1];
114 cs
->RS_CLEAR_CONTROL
= VIVS_RS_CLEAR_CONTROL_BITS(rs
->clear_bits
) | rs
->clear_mode
;
115 cs
->RS_FILL_VALUE
[0] = rs
->clear_value
[0];
116 cs
->RS_FILL_VALUE
[1] = rs
->clear_value
[1];
117 cs
->RS_FILL_VALUE
[2] = rs
->clear_value
[2];
118 cs
->RS_FILL_VALUE
[3] = rs
->clear_value
[3];
119 cs
->RS_EXTRA_CONFIG
= VIVS_RS_EXTRA_CONFIG_AA(rs
->aa
) |
120 VIVS_RS_EXTRA_CONFIG_ENDIAN(rs
->endian_mode
);
121 /* TODO: cs->RS_UNK016B0 = s->size / 64 ?
122 * The blob does this consistently but there seems to be no currently supported
123 * model that needs it.
128 etna_modify_rs_clearbits(struct compiled_rs_state
*cs
, uint32_t clear_bits
)
130 cs
->RS_CLEAR_CONTROL
&= ~VIVS_RS_CLEAR_CONTROL_BITS__MASK
;
131 cs
->RS_CLEAR_CONTROL
|= VIVS_RS_CLEAR_CONTROL_BITS(clear_bits
);