Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

vg_tracker.c 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /**************************************************************************
  2. *
  3. * Copyright 2009 VMware, Inc. All Rights Reserved.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the
  7. * "Software"), to deal in the Software without restriction, including
  8. * without limitation the rights to use, copy, modify, merge, publish,
  9. * distribute, sub license, and/or sell copies of the Software, and to
  10. * permit persons to whom the Software is furnished to do so, subject to
  11. * the following conditions:
  12. *
  13. * The above copyright notice and this permission notice (including the
  14. * next paragraph) shall be included in all copies or substantial portions
  15. * of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  20. * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  21. * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  22. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  23. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. *
  25. **************************************************************************/
  26. #include "vg_context.h"
  27. #include "vg_tracker.h"
  28. #include "mask.h"
  29. #include "pipe/p_context.h"
  30. #include "util/u_inlines.h"
  31. #include "pipe/p_screen.h"
  32. #include "util/u_format.h"
  33. #include "util/u_sampler.h"
  34. #include "util/u_memory.h"
  35. #include "util/u_math.h"
  36. #include "util/u_rect.h"
  37. /* advertise OpenVG support */
  38. PUBLIC const int st_api_OpenVG = 1;
  39. static struct pipe_texture *
  40. create_texture(struct pipe_context *pipe, enum pipe_format format,
  41. VGint width, VGint height)
  42. {
  43. struct pipe_texture templ;
  44. memset(&templ, 0, sizeof(templ));
  45. if (format != PIPE_FORMAT_NONE) {
  46. templ.format = format;
  47. }
  48. else {
  49. templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;
  50. }
  51. templ.target = PIPE_TEXTURE_2D;
  52. templ.width0 = width;
  53. templ.height0 = height;
  54. templ.depth0 = 1;
  55. templ.last_level = 0;
  56. if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) {
  57. templ.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
  58. } else {
  59. templ.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
  60. PIPE_TEXTURE_USAGE_RENDER_TARGET |
  61. PIPE_TEXTURE_USAGE_SAMPLER);
  62. }
  63. return pipe->screen->texture_create(pipe->screen, &templ);
  64. }
  65. static struct pipe_sampler_view *
  66. create_tex_and_view(struct pipe_context *pipe, enum pipe_format format,
  67. VGint width, VGint height)
  68. {
  69. struct pipe_texture *texture;
  70. struct pipe_sampler_view view_templ;
  71. struct pipe_sampler_view *view;
  72. texture = create_texture(pipe, format, width, height);
  73. if (!texture)
  74. return NULL;
  75. u_sampler_view_default_template(&view_templ, texture, texture->format);
  76. view = pipe->create_sampler_view(pipe, texture, &view_templ);
  77. /* want the texture to go away if the view is freed */
  78. pipe_texture_reference(&texture, NULL);
  79. return view;
  80. }
  81. /**
  82. * Allocate a renderbuffer for a an on-screen window (not a user-created
  83. * renderbuffer). The window system code determines the format.
  84. */
  85. static struct st_renderbuffer *
  86. st_new_renderbuffer_fb(enum pipe_format format)
  87. {
  88. struct st_renderbuffer *strb;
  89. strb = CALLOC_STRUCT(st_renderbuffer);
  90. if (!strb) {
  91. /*_vega_error(NULL, VG_OUT_OF_MEMORY, "creating renderbuffer");*/
  92. return NULL;
  93. }
  94. strb->format = format;
  95. return strb;
  96. }
  97. /**
  98. * This is called to allocate the original drawing surface, and
  99. * during window resize.
  100. */
  101. static VGboolean
  102. st_renderbuffer_alloc_storage(struct vg_context * ctx,
  103. struct st_renderbuffer *strb,
  104. VGuint width, VGuint height)
  105. {
  106. struct pipe_context *pipe = ctx->pipe;
  107. unsigned surface_usage;
  108. /* Free the old surface and texture
  109. */
  110. pipe_surface_reference(&strb->surface, NULL);
  111. pipe_texture_reference(&strb->texture, NULL);
  112. /* Probably need dedicated flags for surface usage too:
  113. */
  114. surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
  115. PIPE_BUFFER_USAGE_GPU_WRITE);
  116. strb->texture = create_texture(pipe, strb->format, width, height);
  117. if (!strb->texture)
  118. return FALSE;
  119. strb->surface = pipe->screen->get_tex_surface(pipe->screen,
  120. strb->texture,
  121. 0, 0, 0,
  122. surface_usage);
  123. strb->width = width;
  124. strb->height = height;
  125. assert(strb->surface->width == width);
  126. assert(strb->surface->height == height);
  127. return strb->surface != NULL;
  128. }
  129. struct vg_context * st_create_context(struct pipe_context *pipe,
  130. const void *visual,
  131. struct vg_context *share)
  132. {
  133. struct vg_context *ctx = vg_create_context(pipe, visual, share);
  134. /*debug_printf("--------- CREATE CONTEXT %p\n", ctx);*/
  135. return ctx;
  136. }
  137. void st_destroy_context(struct vg_context *st)
  138. {
  139. /*debug_printf("--------- DESTROY CONTEXT %p\n", st);*/
  140. vg_destroy_context(st);
  141. }
  142. void st_copy_context_state(struct vg_context *dst, struct vg_context *src,
  143. uint mask)
  144. {
  145. fprintf(stderr, "FIXME: %s\n", __FUNCTION__);
  146. }
  147. void st_get_framebuffer_dimensions(struct st_framebuffer *stfb,
  148. uint *width,
  149. uint *height)
  150. {
  151. *width = stfb->strb->width;
  152. *height = stfb->strb->height;
  153. }
  154. struct st_framebuffer * st_create_framebuffer(const void *visual,
  155. enum pipe_format colorFormat,
  156. enum pipe_format depthFormat,
  157. enum pipe_format stencilFormat,
  158. uint width, uint height,
  159. void *privateData)
  160. {
  161. struct st_framebuffer *stfb = CALLOC_STRUCT(st_framebuffer);
  162. if (stfb) {
  163. struct st_renderbuffer *rb =
  164. st_new_renderbuffer_fb(colorFormat);
  165. stfb->strb = rb;
  166. #if 0
  167. if (doubleBuffer) {
  168. struct st_renderbuffer *rb =
  169. st_new_renderbuffer_fb(colorFormat);
  170. }
  171. #endif
  172. /* we want to combine the depth/stencil */
  173. if (stencilFormat == depthFormat)
  174. stfb->dsrb = st_new_renderbuffer_fb(stencilFormat);
  175. else
  176. stfb->dsrb = st_new_renderbuffer_fb(PIPE_FORMAT_Z24S8_UNORM);
  177. /*### currently we always allocate it but it's possible it's
  178. not necessary if EGL_ALPHA_MASK_SIZE was 0
  179. */
  180. stfb->alpha_mask_view = NULL;
  181. stfb->width = width;
  182. stfb->height = height;
  183. stfb->privateData = privateData;
  184. }
  185. return stfb;
  186. }
  187. static void setup_new_alpha_mask(struct vg_context *ctx,
  188. struct st_framebuffer *stfb,
  189. uint width, uint height)
  190. {
  191. struct pipe_context *pipe = ctx->pipe;
  192. struct pipe_sampler_view *old_sampler_view = stfb->alpha_mask_view;
  193. /*
  194. we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to
  195. this texture and use it as a sampler, so while this wastes some
  196. space it makes both of those a lot simpler
  197. */
  198. stfb->alpha_mask_view =
  199. create_tex_and_view(pipe, PIPE_FORMAT_B8G8R8A8_UNORM, width, height);
  200. if (!stfb->alpha_mask_view) {
  201. if (old_sampler_view)
  202. pipe_sampler_view_reference(&old_sampler_view, NULL);
  203. return;
  204. }
  205. vg_validate_state(ctx);
  206. /* alpha mask starts with 1.f alpha */
  207. mask_fill(0, 0, width, height, 1.f);
  208. /* if we had an old surface copy it over */
  209. if (old_sampler_view) {
  210. struct pipe_surface *surface = pipe->screen->get_tex_surface(
  211. pipe->screen,
  212. stfb->alpha_mask_view->texture,
  213. 0, 0, 0,
  214. PIPE_BUFFER_USAGE_GPU_WRITE);
  215. struct pipe_surface *old_surface = pipe->screen->get_tex_surface(
  216. pipe->screen,
  217. old_sampler_view->texture,
  218. 0, 0, 0,
  219. PIPE_BUFFER_USAGE_GPU_READ);
  220. if (pipe->surface_copy) {
  221. pipe->surface_copy(pipe,
  222. surface,
  223. 0, 0,
  224. old_surface,
  225. 0, 0,
  226. MIN2(old_surface->width, width),
  227. MIN2(old_surface->height, height));
  228. } else {
  229. util_surface_copy(pipe, FALSE,
  230. surface,
  231. 0, 0,
  232. old_surface,
  233. 0, 0,
  234. MIN2(old_surface->width, width),
  235. MIN2(old_surface->height, height));
  236. }
  237. if (surface)
  238. pipe_surface_reference(&surface, NULL);
  239. if (old_surface)
  240. pipe_surface_reference(&old_surface, NULL);
  241. }
  242. /* Free the old texture
  243. */
  244. if (old_sampler_view)
  245. pipe_sampler_view_reference(&old_sampler_view, NULL);
  246. }
  247. void st_resize_framebuffer(struct st_framebuffer *stfb,
  248. uint width, uint height)
  249. {
  250. struct vg_context *ctx = vg_current_context();
  251. struct st_renderbuffer *strb = stfb->strb;
  252. struct pipe_framebuffer_state *state;
  253. if (!ctx)
  254. return;
  255. state = &ctx->state.g3d.fb;
  256. /* If this is a noop, exit early and don't do the clear, etc below.
  257. */
  258. if (stfb->width == width &&
  259. stfb->height == height &&
  260. state->zsbuf)
  261. return;
  262. stfb->width = width;
  263. stfb->height = height;
  264. if (strb->width != width || strb->height != height)
  265. st_renderbuffer_alloc_storage(ctx, strb,
  266. width, height);
  267. if (stfb->dsrb->width != width || stfb->dsrb->height != height)
  268. st_renderbuffer_alloc_storage(ctx, stfb->dsrb,
  269. width, height);
  270. {
  271. VGuint i;
  272. memset(state, 0, sizeof(struct pipe_framebuffer_state));
  273. state->width = width;
  274. state->height = height;
  275. state->nr_cbufs = 1;
  276. state->cbufs[0] = strb->surface;
  277. for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
  278. state->cbufs[i] = 0;
  279. state->zsbuf = stfb->dsrb->surface;
  280. cso_set_framebuffer(ctx->cso_context, state);
  281. }
  282. ctx->state.dirty |= VIEWPORT_DIRTY;
  283. ctx->state.dirty |= DEPTH_STENCIL_DIRTY;/*to reset the scissors*/
  284. ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL,
  285. NULL, 0.0, 0);
  286. /* we need all the other state already set */
  287. setup_new_alpha_mask(ctx, stfb, width, height);
  288. pipe_sampler_view_reference( &stfb->blend_texture_view, NULL );
  289. stfb->blend_texture_view = create_tex_and_view(ctx->pipe, PIPE_FORMAT_B8G8R8A8_UNORM,
  290. width, height);
  291. }
  292. void st_set_framebuffer_surface(struct st_framebuffer *stfb,
  293. uint surfIndex, struct pipe_surface *surf)
  294. {
  295. struct st_renderbuffer *rb = stfb->strb;
  296. /* unreference existing surfaces */
  297. pipe_surface_reference( &rb->surface, NULL );
  298. pipe_texture_reference( &rb->texture, NULL );
  299. /* reference new ones */
  300. pipe_surface_reference( &rb->surface, surf );
  301. pipe_texture_reference( &rb->texture, surf->texture );
  302. rb->width = surf->width;
  303. rb->height = surf->height;
  304. }
  305. int st_get_framebuffer_surface(struct st_framebuffer *stfb,
  306. uint surfIndex, struct pipe_surface **surf)
  307. {
  308. struct st_renderbuffer *rb = stfb->strb;
  309. *surf = rb->surface;
  310. return VG_TRUE;
  311. }
  312. int st_get_framebuffer_texture(struct st_framebuffer *stfb,
  313. uint surfIndex, struct pipe_texture **tex)
  314. {
  315. struct st_renderbuffer *rb = stfb->strb;
  316. *tex = rb->texture;
  317. return VG_TRUE;
  318. }
  319. void * st_framebuffer_private(struct st_framebuffer *stfb)
  320. {
  321. return stfb->privateData;
  322. }
  323. void st_unreference_framebuffer(struct st_framebuffer *stfb)
  324. {
  325. /* FIXME */
  326. }
  327. boolean st_make_current(struct vg_context *st,
  328. struct st_framebuffer *draw,
  329. struct st_framebuffer *read,
  330. void *winsys_drawable_handle)
  331. {
  332. vg_set_current_context(st);
  333. if (st)
  334. st->draw_buffer = draw;
  335. return VG_TRUE;
  336. }
  337. struct vg_context *st_get_current(void)
  338. {
  339. return vg_current_context();
  340. }
  341. void st_flush(struct vg_context *st, uint pipeFlushFlags,
  342. struct pipe_fence_handle **fence)
  343. {
  344. st->pipe->flush(st->pipe, pipeFlushFlags, fence);
  345. }
  346. void st_finish(struct vg_context *st)
  347. {
  348. struct pipe_fence_handle *fence = NULL;
  349. st_flush(st, PIPE_FLUSH_RENDER_CACHE, &fence);
  350. st->pipe->screen->fence_finish(st->pipe->screen, fence, 0);
  351. st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL);
  352. }
  353. void st_notify_swapbuffers(struct st_framebuffer *stfb)
  354. {
  355. struct vg_context *ctx = vg_current_context();
  356. if (ctx && ctx->draw_buffer == stfb) {
  357. st_flush(ctx,
  358. PIPE_FLUSH_RENDER_CACHE |
  359. PIPE_FLUSH_SWAPBUFFERS |
  360. PIPE_FLUSH_FRAME,
  361. NULL);
  362. }
  363. }
  364. void st_notify_swapbuffers_complete(struct st_framebuffer *stfb)
  365. {
  366. }
  367. int st_bind_texture_surface(struct pipe_surface *ps, int target, int level,
  368. enum pipe_format format)
  369. {
  370. return 0;
  371. }
  372. int st_unbind_texture_surface(struct pipe_surface *ps, int target, int level)
  373. {
  374. return 0;
  375. }
  376. st_proc st_get_proc_address(const char *procname)
  377. {
  378. return NULL;
  379. }