902a48e6b47987b5c1693559dd6dbe67dc230915
[profile/ivi/mesa.git] / src / gallium / state_trackers / dri / common / dri_st_api.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  7.9
4  *
5  * Copyright (C) 2010 LunarG Inc.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the 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
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  *
25  * Authors:
26  *    Chia-I Wu <olv@lunarg.com>
27  */
28
29 #include "util/u_memory.h"
30 #include "util/u_inlines.h"
31 #include "util/u_format.h"
32 #include "util/u_debug.h"
33 #include "state_tracker/st_manager.h" /* for st_manager_create_api */
34
35 #include "dri_screen.h"
36 #include "dri_context.h"
37 #include "dri_drawable.h"
38 #include "dri_st_api.h"
39 #ifndef __NOT_HAVE_DRM_H
40 #include "dri1.h"
41 #include "dri2.h"
42 #else
43 #include "drisw.h"
44 #endif
45
46 static boolean
47 dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
48                             const enum st_attachment_type *statts,
49                             unsigned count,
50                             struct pipe_texture **out)
51 {
52    struct dri_drawable *drawable =
53       (struct dri_drawable *) stfbi->st_manager_private;
54    unsigned statt_mask, new_mask;
55    boolean new_stamp;
56    int i;
57
58    statt_mask = 0x0;
59    for (i = 0; i < count; i++)
60       statt_mask |= (1 << statts[i]);
61
62    /* record newly allocated textures */
63    new_mask = (statt_mask & ~drawable->texture_mask);
64
65    /*
66     * dPriv->pStamp is the server stamp.  It should be accessed with a lock, at
67     * least for DRI1.  dPriv->lastStamp is the client stamp.  It has the value
68     * of the server stamp when last checked.
69     */
70    new_stamp = (drawable->texture_stamp != drawable->dPriv->lastStamp);
71
72    if (new_stamp || new_mask) {
73
74 #ifndef __NOT_HAVE_DRM_H
75       if (__dri1_api_hooks) {
76          dri1_allocate_textures(drawable, statt_mask);
77       }
78       else {
79          dri2_allocate_textures(drawable, statts, count);
80       }
81 #else
82       if (new_stamp)
83          drisw_update_drawable_info(drawable);
84
85       drisw_allocate_textures(drawable, statt_mask);
86 #endif
87
88       /* add existing textures */
89       for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
90          if (drawable->textures[i])
91             statt_mask |= (1 << i);
92       }
93
94       drawable->texture_stamp = drawable->dPriv->lastStamp;
95       drawable->texture_mask = statt_mask;
96    }
97
98    if (!out)
99       return TRUE;
100
101    for (i = 0; i < count; i++) {
102       out[i] = NULL;
103       pipe_texture_reference(&out[i], drawable->textures[statts[i]]);
104    }
105
106    return TRUE;
107 }
108
109 static boolean
110 dri_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
111                                enum st_attachment_type statt)
112 {
113    struct dri_drawable *drawable =
114       (struct dri_drawable *) stfbi->st_manager_private;
115
116 #ifndef __NOT_HAVE_DRM_H
117    if (__dri1_api_hooks) {
118       dri1_flush_frontbuffer(drawable, statt);
119    }
120    else {
121       dri2_flush_frontbuffer(drawable, statt);
122    }
123 #else
124    drisw_flush_frontbuffer(drawable, statt);
125 #endif
126
127    return TRUE;
128 }
129
130 /**
131  * Create a framebuffer from the given drawable.
132  */
133 struct st_framebuffer_iface *
134 dri_create_st_framebuffer(struct dri_drawable *drawable)
135 {
136    struct st_framebuffer_iface *stfbi;
137
138    stfbi = CALLOC_STRUCT(st_framebuffer_iface);
139    if (stfbi) {
140       stfbi->visual = &drawable->stvis;
141       stfbi->flush_front = dri_st_framebuffer_flush_front;
142       stfbi->validate = dri_st_framebuffer_validate;
143       stfbi->st_manager_private = (void *) drawable;
144    }
145
146    return stfbi;
147 }
148
149 /**
150  * Destroy a framebuffer.
151  */
152 void
153 dri_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
154 {
155    struct dri_drawable *drawable =
156       (struct dri_drawable *) stfbi->st_manager_private;
157    int i;
158
159    for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
160       pipe_texture_reference(&drawable->textures[i], NULL);
161
162    FREE(stfbi);
163 }
164
165 /**
166  * Validate the texture at an attachment.  Allocate the texture if it does not
167  * exist.
168  */
169 void
170 dri_st_framebuffer_validate_att(struct st_framebuffer_iface *stfbi,
171                                 enum st_attachment_type statt)
172 {
173    struct dri_drawable *drawable =
174       (struct dri_drawable *) stfbi->st_manager_private;
175    enum st_attachment_type statts[ST_ATTACHMENT_COUNT];
176    unsigned i, count = 0;
177
178    /* check if buffer already exists */
179    if (drawable->texture_mask & (1 << statt))
180       return;
181
182    /* make sure DRI2 does not destroy existing buffers */
183    for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
184       if (drawable->texture_mask & (1 << i)) {
185          statts[count++] = i;
186       }
187    }
188    statts[count++] = statt;
189
190    drawable->texture_stamp = drawable->dPriv->lastStamp - 1;
191
192    stfbi->validate(stfbi, statts, count, NULL);
193 }
194
195 /**
196  * Reference counted st_api.
197  */
198 static struct {
199    int32_t refcnt;
200    struct st_api *stapi;
201 } dri_st_api;
202
203 /**
204  * Add a reference to the st_api of the state tracker.
205  */
206 static void
207 _dri_get_st_api(void)
208 {
209    p_atomic_inc(&dri_st_api.refcnt);
210    if (p_atomic_read(&dri_st_api.refcnt) == 1)
211       dri_st_api.stapi = st_manager_create_api();
212 }
213
214 /**
215  * Remove a reference to the st_api of the state tracker.
216  */
217 static void
218 _dri_put_st_api(void)
219 {
220    struct st_api *stapi = dri_st_api.stapi;
221
222    if (p_atomic_dec_zero(&dri_st_api.refcnt)) {
223       stapi->destroy(dri_st_api.stapi);
224       dri_st_api.stapi = NULL;
225    }
226 }
227
228 static boolean
229 dri_st_manager_get_egl_image(struct st_manager *smapi,
230                              struct st_egl_image *stimg)
231 {
232    __DRIimage *img = NULL;
233
234 #ifndef __NOT_HAVE_DRM_H
235    if (!__dri1_api_hooks) {
236       struct dri_context *ctx = (struct dri_context *)
237          stimg->stctxi->st_manager_private;
238       img = dri2_lookup_egl_image(ctx, stimg->egl_image);
239    }
240 #endif
241    if (!img)
242       return FALSE;
243
244    stimg->texture = NULL;
245    pipe_texture_reference(&stimg->texture, img->texture);
246    stimg->face = img->face;
247    stimg->level = img->level;
248    stimg->zslice = img->zslice;
249
250    return TRUE;
251 }
252
253 /**
254  * Create a state tracker manager from the given screen.
255  */
256 struct st_manager *
257 dri_create_st_manager(struct dri_screen *screen)
258 {
259    struct st_manager *smapi;
260
261    smapi = CALLOC_STRUCT(st_manager);
262    if (smapi) {
263       smapi->screen = screen->pipe_screen;
264       smapi->get_egl_image = dri_st_manager_get_egl_image;
265       _dri_get_st_api();
266    }
267
268    return smapi;
269 }
270
271 /**
272  * Destroy a state tracker manager.
273  */
274 void
275 dri_destroy_st_manager(struct st_manager *smapi)
276 {
277    _dri_put_st_api();
278    FREE(smapi);
279 }
280
281 /**
282  * Return the st_api of OpenGL state tracker.
283  */
284 struct st_api *
285 dri_get_st_api(void)
286 {
287    assert(dri_st_api.stapi);
288    return dri_st_api.stapi;
289 }