Home | History | Annotate | Download | only in freedreno
      1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
      2 
      3 /*
      4  * Copyright (C) 2012 Rob Clark <robclark (at) freedesktop.org>
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  *
     25  * Authors:
     26  *    Rob Clark <robclark (at) freedesktop.org>
     27  */
     28 
     29 #ifdef HAVE_CONFIG_H
     30 # include <config.h>
     31 #endif
     32 
     33 #include <assert.h>
     34 
     35 #include "freedreno_drmif.h"
     36 #include "freedreno_priv.h"
     37 #include "freedreno_ringbuffer.h"
     38 
     39 struct fd_ringbuffer *
     40 fd_ringbuffer_new(struct fd_pipe *pipe, uint32_t size)
     41 {
     42 	struct fd_ringbuffer *ring;
     43 
     44 	ring = pipe->funcs->ringbuffer_new(pipe, size);
     45 	if (!ring)
     46 		return NULL;
     47 
     48 	ring->pipe = pipe;
     49 	ring->start = ring->funcs->hostptr(ring);
     50 	ring->end = &(ring->start[ring->size/4]);
     51 
     52 	ring->cur = ring->last_start = ring->start;
     53 
     54 	return ring;
     55 }
     56 
     57 void fd_ringbuffer_del(struct fd_ringbuffer *ring)
     58 {
     59 	fd_ringbuffer_reset(ring);
     60 	ring->funcs->destroy(ring);
     61 }
     62 
     63 /* ringbuffers which are IB targets should set the toplevel rb (ie.
     64  * the IB source) as it's parent before emitting reloc's, to ensure
     65  * the bookkeeping works out properly.
     66  */
     67 void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring,
     68 					 struct fd_ringbuffer *parent)
     69 {
     70 	ring->parent = parent;
     71 }
     72 
     73 void fd_ringbuffer_reset(struct fd_ringbuffer *ring)
     74 {
     75 	uint32_t *start = ring->start;
     76 	if (ring->pipe->id == FD_PIPE_2D)
     77 		start = &ring->start[0x140];
     78 	ring->cur = ring->last_start = start;
     79 	if (ring->funcs->reset)
     80 		ring->funcs->reset(ring);
     81 }
     82 
     83 int fd_ringbuffer_flush(struct fd_ringbuffer *ring)
     84 {
     85 	return ring->funcs->flush(ring, ring->last_start, -1, NULL);
     86 }
     87 
     88 int fd_ringbuffer_flush2(struct fd_ringbuffer *ring, int in_fence_fd,
     89 		int *out_fence_fd)
     90 {
     91 	return ring->funcs->flush(ring, ring->last_start, in_fence_fd, out_fence_fd);
     92 }
     93 
     94 void fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords)
     95 {
     96 	assert(ring->funcs->grow);     /* unsupported on kgsl */
     97 
     98 	/* there is an upper bound on IB size, which appears to be 0x100000 */
     99 	if (ring->size < 0x100000)
    100 		ring->size *= 2;
    101 
    102 	ring->funcs->grow(ring, ring->size);
    103 
    104 	ring->start = ring->funcs->hostptr(ring);
    105 	ring->end = &(ring->start[ring->size/4]);
    106 
    107 	ring->cur = ring->last_start = ring->start;
    108 }
    109 
    110 uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring)
    111 {
    112 	return ring->last_timestamp;
    113 }
    114 
    115 void fd_ringbuffer_reloc(struct fd_ringbuffer *ring,
    116 				    const struct fd_reloc *reloc)
    117 {
    118 	assert(ring->pipe->gpu_id < 500);
    119 	ring->funcs->emit_reloc(ring, reloc);
    120 }
    121 
    122 void fd_ringbuffer_reloc2(struct fd_ringbuffer *ring,
    123 				     const struct fd_reloc *reloc)
    124 {
    125 	ring->funcs->emit_reloc(ring, reloc);
    126 }
    127 
    128 void fd_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring,
    129 		struct fd_ringmarker *target, struct fd_ringmarker *end)
    130 {
    131 	uint32_t submit_offset, size;
    132 
    133 	/* This function is deprecated and not supported on 64b devices: */
    134 	assert(ring->pipe->gpu_id < 500);
    135 	assert(target->ring == end->ring);
    136 
    137 	submit_offset = offset_bytes(target->cur, target->ring->start);
    138 	size = offset_bytes(end->cur, target->cur);
    139 
    140 	ring->funcs->emit_reloc_ring(ring, target->ring, 0, submit_offset, size);
    141 }
    142 
    143 uint32_t fd_ringbuffer_cmd_count(struct fd_ringbuffer *ring)
    144 {
    145 	if (!ring->funcs->cmd_count)
    146 		return 1;
    147 	return ring->funcs->cmd_count(ring);
    148 }
    149 
    150 uint32_t
    151 fd_ringbuffer_emit_reloc_ring_full(struct fd_ringbuffer *ring,
    152 		struct fd_ringbuffer *target, uint32_t cmd_idx)
    153 {
    154 	uint32_t size = offset_bytes(target->cur, target->start);
    155 	return ring->funcs->emit_reloc_ring(ring, target, cmd_idx, 0, size);
    156 }
    157 
    158 struct fd_ringmarker * fd_ringmarker_new(struct fd_ringbuffer *ring)
    159 {
    160 	struct fd_ringmarker *marker = NULL;
    161 
    162 	marker = calloc(1, sizeof(*marker));
    163 	if (!marker) {
    164 		ERROR_MSG("allocation failed");
    165 		return NULL;
    166 	}
    167 
    168 	marker->ring = ring;
    169 
    170 	marker->cur = marker->ring->cur;
    171 
    172 	return marker;
    173 }
    174 
    175 void fd_ringmarker_del(struct fd_ringmarker *marker)
    176 {
    177 	free(marker);
    178 }
    179 
    180 void fd_ringmarker_mark(struct fd_ringmarker *marker)
    181 {
    182 	marker->cur = marker->ring->cur;
    183 }
    184 
    185 uint32_t fd_ringmarker_dwords(struct fd_ringmarker *start,
    186 					 struct fd_ringmarker *end)
    187 {
    188 	return end->cur - start->cur;
    189 }
    190 
    191 int fd_ringmarker_flush(struct fd_ringmarker *marker)
    192 {
    193 	struct fd_ringbuffer *ring = marker->ring;
    194 	return ring->funcs->flush(ring, marker->cur, -1, NULL);
    195 }
    196