1/*
2 * Mesa 3-D graphics library
3 * Version:  7.12
4 *
5 * Copyright (C) 2010-2011 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 "pipe/p_compiler.h"
30#include "pipe/p_state.h"
31#include "util/u_memory.h"
32#include "util/u_format.h"
33#include "state_tracker/sw_winsys.h"
34
35#include <hardware/gralloc.h>
36#include <utils/Errors.h>
37
38#if ANDROID_VERSION < 0x0300
39#include <private/ui/sw_gralloc_handle.h>
40#endif
41
42#include "android_sw_winsys.h"
43
44struct android_sw_winsys
45{
46   struct sw_winsys base;
47
48   const gralloc_module_t *grmod;
49};
50
51struct android_sw_displaytarget
52{
53   buffer_handle_t handle;
54   int stride;
55   int width, height;
56   int usage; /* gralloc usage */
57
58   void *mapped;
59};
60
61static INLINE struct android_sw_winsys *
62android_sw_winsys(struct sw_winsys *ws)
63{
64   return (struct android_sw_winsys *) ws;
65}
66
67static INLINE struct android_sw_displaytarget *
68android_sw_displaytarget(struct sw_displaytarget *dt)
69{
70   return (struct android_sw_displaytarget *) dt;
71}
72
73namespace android {
74
75static void
76android_displaytarget_display(struct sw_winsys *ws,
77                              struct sw_displaytarget *dt,
78                              void *context_private)
79{
80}
81
82static struct sw_displaytarget *
83android_displaytarget_create(struct sw_winsys *ws,
84                             unsigned tex_usage,
85                             enum pipe_format format,
86                             unsigned width, unsigned height,
87                             unsigned alignment,
88                             unsigned *stride)
89{
90   return NULL;
91}
92
93static void
94android_displaytarget_destroy(struct sw_winsys *ws,
95                              struct sw_displaytarget *dt)
96{
97   struct android_sw_displaytarget *adt = android_sw_displaytarget(dt);
98
99   assert(!adt->mapped);
100   FREE(adt);
101}
102
103static void
104android_displaytarget_unmap(struct sw_winsys *ws,
105                            struct sw_displaytarget *dt)
106{
107   struct android_sw_winsys *droid = android_sw_winsys(ws);
108   struct android_sw_displaytarget *adt = android_sw_displaytarget(dt);
109
110#if ANDROID_VERSION < 0x0300
111   /* try sw_gralloc first */
112   if (adt->mapped && sw_gralloc_handle_t::validate(adt->handle) >= 0) {
113      adt->mapped = NULL;
114      return;
115   }
116#endif
117
118   if (adt->mapped) {
119      droid->grmod->unlock(droid->grmod, adt->handle);
120      adt->mapped = NULL;
121   }
122}
123
124static void *
125android_displaytarget_map(struct sw_winsys *ws,
126                          struct sw_displaytarget *dt,
127                          unsigned flags)
128{
129   struct android_sw_winsys *droid = android_sw_winsys(ws);
130   struct android_sw_displaytarget *adt = android_sw_displaytarget(dt);
131
132#if ANDROID_VERSION < 0x0300
133   /* try sw_gralloc first */
134   if (sw_gralloc_handle_t::validate(adt->handle) >= 0) {
135      const sw_gralloc_handle_t *swhandle =
136         reinterpret_cast<const sw_gralloc_handle_t *>(adt->handle);
137      adt->mapped = reinterpret_cast<void *>(swhandle->base);
138
139      return adt->mapped;
140   }
141#endif
142
143   if (!adt->mapped) {
144      /* lock the buffer for CPU access */
145      droid->grmod->lock(droid->grmod, adt->handle,
146            adt->usage, 0, 0, adt->width, adt->height, &adt->mapped);
147   }
148
149   return adt->mapped;
150}
151
152static struct sw_displaytarget *
153android_displaytarget_from_handle(struct sw_winsys *ws,
154                                  const struct pipe_resource *templ,
155                                  struct winsys_handle *whandle,
156                                  unsigned *stride)
157{
158   struct android_winsys_handle *ahandle =
159      (struct android_winsys_handle *) whandle;
160   struct android_sw_displaytarget *adt;
161
162   adt = CALLOC_STRUCT(android_sw_displaytarget);
163   if (!adt)
164      return NULL;
165
166   adt->handle = ahandle->handle;
167   adt->stride = ahandle->stride;
168   adt->width = templ->width0;
169   adt->height = templ->height0;
170
171   if (templ->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_TRANSFER_WRITE))
172      adt->usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
173   if (templ->bind & (PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_TRANSFER_READ))
174      adt->usage |= GRALLOC_USAGE_SW_READ_OFTEN;
175
176   if (stride)
177      *stride = adt->stride;
178
179   return reinterpret_cast<struct sw_displaytarget *>(adt);
180}
181
182static boolean
183android_displaytarget_get_handle(struct sw_winsys *ws,
184                                 struct sw_displaytarget *dt,
185                                 struct winsys_handle *whandle)
186{
187   return FALSE;
188}
189
190static boolean
191android_is_displaytarget_format_supported(struct sw_winsys *ws,
192                                          unsigned tex_usage,
193                                          enum pipe_format format)
194{
195   struct android_sw_winsys *droid = android_sw_winsys(ws);
196   int fmt = -1;
197
198   switch (format) {
199   case PIPE_FORMAT_R8G8B8A8_UNORM:
200      fmt = HAL_PIXEL_FORMAT_RGBA_8888;
201      break;
202   case PIPE_FORMAT_R8G8B8X8_UNORM:
203      fmt = HAL_PIXEL_FORMAT_RGBX_8888;
204      break;
205   case PIPE_FORMAT_R8G8B8_UNORM:
206      fmt = HAL_PIXEL_FORMAT_RGB_888;
207      break;
208   case PIPE_FORMAT_B5G6R5_UNORM:
209      fmt = HAL_PIXEL_FORMAT_RGB_565;
210      break;
211   case PIPE_FORMAT_B8G8R8A8_UNORM:
212      fmt = HAL_PIXEL_FORMAT_BGRA_8888;
213      break;
214   default:
215      break;
216   }
217
218   return (fmt != -1);
219}
220
221static void
222android_destroy(struct sw_winsys *ws)
223{
224   struct android_sw_winsys *droid = android_sw_winsys(ws);
225
226   FREE(droid);
227}
228
229}; /* namespace android */
230
231using namespace android;
232
233struct sw_winsys *
234android_create_sw_winsys(void)
235{
236   struct android_sw_winsys *droid;
237   const hw_module_t *mod;
238
239   droid = CALLOC_STRUCT(android_sw_winsys);
240   if (!droid)
241      return NULL;
242
243   if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod)) {
244      FREE(droid);
245      return NULL;
246   }
247
248   droid->grmod = (const gralloc_module_t *) mod;
249
250   droid->base.destroy = android_destroy;
251   droid->base.is_displaytarget_format_supported =
252      android_is_displaytarget_format_supported;
253
254   droid->base.displaytarget_create = android_displaytarget_create;
255   droid->base.displaytarget_destroy = android_displaytarget_destroy;
256   droid->base.displaytarget_from_handle = android_displaytarget_from_handle;
257   droid->base.displaytarget_get_handle = android_displaytarget_get_handle;
258
259   droid->base.displaytarget_map = android_displaytarget_map;
260   droid->base.displaytarget_unmap = android_displaytarget_unmap;
261   droid->base.displaytarget_display = android_displaytarget_display;
262
263   return &droid->base;
264}
265