1af69d88dSmrg/*
2af69d88dSmrg * Copyright 2013 Marek Olšák <maraeo@gmail.com>
3af69d88dSmrg *
4af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5af69d88dSmrg * copy of this software and associated documentation files (the "Software"),
6af69d88dSmrg * to deal in the Software without restriction, including without limitation
7af69d88dSmrg * on the rights to use, copy, modify, merge, publish, distribute, sub
8af69d88dSmrg * license, and/or sell copies of the Software, and to permit persons to whom
9af69d88dSmrg * the Software is furnished to do so, subject to the following conditions:
10af69d88dSmrg *
11af69d88dSmrg * The above copyright notice and this permission notice (including the next
12af69d88dSmrg * paragraph) shall be included in all copies or substantial portions of the
13af69d88dSmrg * Software.
14af69d88dSmrg *
15af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16af69d88dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18af69d88dSmrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19af69d88dSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20af69d88dSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21af69d88dSmrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22af69d88dSmrg
23af69d88dSmrg/**
24af69d88dSmrg * @file
25af69d88dSmrg * 1D integer range, capable of the union and intersection operations.
26af69d88dSmrg *
27af69d88dSmrg * It only maintains a single interval which is extended when the union is
28af69d88dSmrg * done. This implementation is partially thread-safe (readers are not
29af69d88dSmrg * protected by a lock).
30af69d88dSmrg *
31af69d88dSmrg * @author Marek Olšák
32af69d88dSmrg */
33af69d88dSmrg
34af69d88dSmrg#ifndef U_RANGE_H
35af69d88dSmrg#define U_RANGE_H
36af69d88dSmrg
37af69d88dSmrg#include "os/os_thread.h"
387ec681f3Smrg#include "pipe/p_state.h"
397ec681f3Smrg#include "pipe/p_screen.h"
407ec681f3Smrg#include "util/u_atomic.h"
41af69d88dSmrg#include "util/u_math.h"
427ec681f3Smrg#include "util/simple_mtx.h"
43af69d88dSmrg
44af69d88dSmrgstruct util_range {
45af69d88dSmrg   unsigned start; /* inclusive */
46af69d88dSmrg   unsigned end; /* exclusive */
47af69d88dSmrg
48af69d88dSmrg   /* for the range to be consistent with multiple contexts: */
497ec681f3Smrg   simple_mtx_t write_mutex;
50af69d88dSmrg};
51af69d88dSmrg
52af69d88dSmrg
5301e04c3fSmrgstatic inline void
54af69d88dSmrgutil_range_set_empty(struct util_range *range)
55af69d88dSmrg{
56af69d88dSmrg   range->start = ~0;
57af69d88dSmrg   range->end = 0;
58af69d88dSmrg}
59af69d88dSmrg
60af69d88dSmrg/* This is like a union of two sets. */
6101e04c3fSmrgstatic inline void
627ec681f3Smrgutil_range_add(struct pipe_resource *resource, struct util_range *range,
637ec681f3Smrg               unsigned start, unsigned end)
64af69d88dSmrg{
65af69d88dSmrg   if (start < range->start || end > range->end) {
667ec681f3Smrg      if (resource->flags & PIPE_RESOURCE_FLAG_SINGLE_THREAD_USE ||
677ec681f3Smrg          p_atomic_read(&resource->screen->num_contexts) == 1) {
687ec681f3Smrg         range->start = MIN2(start, range->start);
697ec681f3Smrg         range->end = MAX2(end, range->end);
707ec681f3Smrg      } else {
717ec681f3Smrg         simple_mtx_lock(&range->write_mutex);
727ec681f3Smrg         range->start = MIN2(start, range->start);
737ec681f3Smrg         range->end = MAX2(end, range->end);
747ec681f3Smrg         simple_mtx_unlock(&range->write_mutex);
757ec681f3Smrg      }
76af69d88dSmrg   }
77af69d88dSmrg}
78af69d88dSmrg
7901e04c3fSmrgstatic inline boolean
80361fc4cbSmayautil_ranges_intersect(const struct util_range *range,
81361fc4cbSmaya                      unsigned start, unsigned end)
82af69d88dSmrg{
83af69d88dSmrg   return MAX2(start, range->start) < MIN2(end, range->end);
84af69d88dSmrg}
85af69d88dSmrg
86af69d88dSmrg
87af69d88dSmrg/* Init/deinit */
88af69d88dSmrg
8901e04c3fSmrgstatic inline void
90af69d88dSmrgutil_range_init(struct util_range *range)
91af69d88dSmrg{
927ec681f3Smrg   (void) simple_mtx_init(&range->write_mutex, mtx_plain);
93af69d88dSmrg   util_range_set_empty(range);
94af69d88dSmrg}
95af69d88dSmrg
9601e04c3fSmrgstatic inline void
97af69d88dSmrgutil_range_destroy(struct util_range *range)
98af69d88dSmrg{
997ec681f3Smrg   simple_mtx_destroy(&range->write_mutex);
100af69d88dSmrg}
101af69d88dSmrg
102af69d88dSmrg#endif
103