1/*
2 * Copyright © 2017 Red Hat
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 (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
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 NONINFRINGEMENT.  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 FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#ifndef _U_TRANSFER_HELPER_H
25#define _U_TRANSFER_HELPER_H
26
27#include "pipe/p_state.h"
28#include "pipe/p_context.h"
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34/* A helper to implement various "lowering" for transfers:
35 *
36 *  - exposing separate depth and stencil resources as packed depth-stencil
37 *  - fake RGTC support for GLES class hardware which needs it to expose GL3+
38 *  - MSAA resolves
39 *
40 * To use this, drivers should:
41 *
42 *  1) populate u_transfer_vtbl and plug that into pipe_screen::transfer_helper
43 *  2) plug the transfer helpers into pipe_screen/pipe_context
44 *
45 * To avoid subclassing pipe_resource (and conflicting with threaded_context)
46 * the vtbl contains setter/getter methods used for fake_rgct & separate_stencil
47 * to access the internal_format and separate stencil buffer.
48 */
49
50struct u_transfer_vtbl {
51   /* NOTE I am not expecting resource_create_from_handle() or
52    * resource_create_with_modifiers() paths to be creating any
53    * resources that need special handling.  Otherwise they would
54    * need to be wrapped too.
55    */
56   struct pipe_resource * (*resource_create)(struct pipe_screen *pscreen,
57                                             const struct pipe_resource *templ);
58
59   void (*resource_destroy)(struct pipe_screen *pscreen,
60                            struct pipe_resource *prsc);
61
62   void *(*transfer_map)(struct pipe_context *pctx,
63                         struct pipe_resource *prsc,
64                         unsigned level,
65                         unsigned usage,
66                         const struct pipe_box *box,
67                         struct pipe_transfer **pptrans);
68
69
70   void (*transfer_flush_region)(struct pipe_context *pctx,
71                                 struct pipe_transfer *ptrans,
72                                 const struct pipe_box *box);
73
74   void (*transfer_unmap)(struct pipe_context *pctx,
75                          struct pipe_transfer *ptrans);
76
77   /*
78    * auxiliary methods to access internal format, stencil:
79    */
80
81   /**
82    * Must be implemented if separate stencil or fake_rgtc is used.  The
83    * internal_format is the format the resource was created with.  In
84    * the case of separate stencil or fake_rgtc, prsc->format is set back
85    * to the gallium-frontend-visible format (e.g. Z32_FLOAT_S8X24_UINT or
86    * PIPE_FORMAT_{RTGC,LATC}* after the resource is created.
87    */
88   enum pipe_format (*get_internal_format)(struct pipe_resource *prsc);
89
90   /**
91    * Must be implemented if separate stencil is lowered.  Used to set/get
92    * the separate s8 stencil buffer.
93    *
94    * These two do not get/put references to the pipe_resource.  The
95    * stencil resource will be destroyed by u_transfer_helper_resource_destroy().
96    */
97   void (*set_stencil)(struct pipe_resource *prsc, struct pipe_resource *stencil);
98   struct pipe_resource *(*get_stencil)(struct pipe_resource *prsc);
99};
100
101struct pipe_resource *u_transfer_helper_resource_create(
102      struct pipe_screen *pscreen, const struct pipe_resource *templ);
103
104void u_transfer_helper_resource_destroy(struct pipe_screen *pscreen,
105                                        struct pipe_resource *prsc);
106
107void *u_transfer_helper_transfer_map(struct pipe_context *pctx,
108                                     struct pipe_resource *prsc,
109                                     unsigned level,
110                                     unsigned usage,
111                                     const struct pipe_box *box,
112                                     struct pipe_transfer **pptrans);
113
114
115void u_transfer_helper_transfer_flush_region(struct pipe_context *pctx,
116                                             struct pipe_transfer *ptrans,
117                                             const struct pipe_box *box);
118
119void u_transfer_helper_transfer_unmap(struct pipe_context *pctx,
120                                      struct pipe_transfer *ptrans);
121
122struct u_transfer_helper;
123
124struct u_transfer_helper * u_transfer_helper_create(const struct u_transfer_vtbl *vtbl,
125                                                    bool separate_z32s8,
126                                                    bool separate_stencil,
127                                                    bool fake_rgtc,
128                                                    bool msaa_map,
129                                                    bool z24_in_z32f);
130
131void u_transfer_helper_destroy(struct u_transfer_helper *helper);
132
133void *
134u_transfer_helper_deinterleave_transfer_map(struct pipe_context *pctx,
135                                            struct pipe_resource *prsc,
136                                            unsigned level, unsigned usage,
137                                            const struct pipe_box *box,
138                                            struct pipe_transfer **pptrans);
139
140void
141u_transfer_helper_deinterleave_transfer_unmap(struct pipe_context *pctx,
142                                              struct pipe_transfer *ptrans);
143#ifdef __cplusplus
144} // extern "C" {
145#endif
146
147#endif /* _U_TRANSFER_HELPER_H */
148