Clone of mesa.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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. /**
  27. * @file
  28. * Surface utility functions.
  29. *
  30. * @author Brian Paul
  31. */
  32. #include "pipe/p_defines.h"
  33. #include "pipe/p_screen.h"
  34. #include "pipe/p_state.h"
  35. #include "util/u_format.h"
  36. #include "util/u_inlines.h"
  37. #include "util/u_rect.h"
  38. #include "util/u_surface.h"
  39. #include "util/u_pack_color.h"
  40. void
  41. u_surface_default_template(struct pipe_surface *view,
  42. const struct pipe_resource *texture,
  43. unsigned bind)
  44. {
  45. view->format = texture->format;
  46. view->u.tex.level = 0;
  47. view->u.tex.first_layer = 0;
  48. view->u.tex.last_layer = 0;
  49. /* XXX should filter out all non-rt/ds bind flags ? */
  50. view->usage = bind;
  51. }
  52. /**
  53. * Helper to quickly create an RGBA rendering surface of a certain size.
  54. * \param textureOut returns the new texture
  55. * \param surfaceOut returns the new surface
  56. * \return TRUE for success, FALSE if failure
  57. */
  58. boolean
  59. util_create_rgba_surface(struct pipe_context *pipe,
  60. uint width, uint height,
  61. uint bind,
  62. struct pipe_resource **textureOut,
  63. struct pipe_surface **surfaceOut)
  64. {
  65. static const enum pipe_format rgbaFormats[] = {
  66. PIPE_FORMAT_B8G8R8A8_UNORM,
  67. PIPE_FORMAT_A8R8G8B8_UNORM,
  68. PIPE_FORMAT_A8B8G8R8_UNORM,
  69. PIPE_FORMAT_NONE
  70. };
  71. const uint target = PIPE_TEXTURE_2D;
  72. enum pipe_format format = PIPE_FORMAT_NONE;
  73. struct pipe_resource templ;
  74. struct pipe_surface surf_templ;
  75. struct pipe_screen *screen = pipe->screen;
  76. uint i;
  77. /* Choose surface format */
  78. for (i = 0; rgbaFormats[i]; i++) {
  79. if (screen->is_format_supported(screen, rgbaFormats[i],
  80. target, 0, bind)) {
  81. format = rgbaFormats[i];
  82. break;
  83. }
  84. }
  85. if (format == PIPE_FORMAT_NONE)
  86. return FALSE; /* unable to get an rgba format!?! */
  87. /* create texture */
  88. memset(&templ, 0, sizeof(templ));
  89. templ.target = target;
  90. templ.format = format;
  91. templ.last_level = 0;
  92. templ.width0 = width;
  93. templ.height0 = height;
  94. templ.depth0 = 1;
  95. templ.array_size = 1;
  96. templ.bind = bind;
  97. *textureOut = screen->resource_create(screen, &templ);
  98. if (!*textureOut)
  99. return FALSE;
  100. /* create surface */
  101. memset(&surf_templ, 0, sizeof(surf_templ));
  102. u_surface_default_template(&surf_templ, *textureOut, bind);
  103. /* create surface / view into texture */
  104. *surfaceOut = pipe->create_surface(pipe,
  105. *textureOut,
  106. &surf_templ);
  107. if (!*surfaceOut) {
  108. pipe_resource_reference(textureOut, NULL);
  109. return FALSE;
  110. }
  111. return TRUE;
  112. }
  113. /**
  114. * Release the surface and texture from util_create_rgba_surface().
  115. */
  116. void
  117. util_destroy_rgba_surface(struct pipe_resource *texture,
  118. struct pipe_surface *surface)
  119. {
  120. pipe_surface_reference(&surface, NULL);
  121. pipe_resource_reference(&texture, NULL);
  122. }
  123. /**
  124. * Fallback function for pipe->resource_copy_region().
  125. * Note: (X,Y)=(0,0) is always the upper-left corner.
  126. */
  127. void
  128. util_resource_copy_region(struct pipe_context *pipe,
  129. struct pipe_resource *dst,
  130. unsigned dst_level,
  131. unsigned dst_x, unsigned dst_y, unsigned dst_z,
  132. struct pipe_resource *src,
  133. unsigned src_level,
  134. const struct pipe_box *src_box)
  135. {
  136. struct pipe_transfer *src_trans, *dst_trans;
  137. void *dst_map;
  138. const void *src_map;
  139. enum pipe_format src_format, dst_format;
  140. unsigned w = src_box->width;
  141. unsigned h = src_box->height;
  142. assert(src && dst);
  143. assert((src->target == PIPE_BUFFER && dst->target == PIPE_BUFFER) ||
  144. (src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER));
  145. if (!src || !dst)
  146. return;
  147. src_format = src->format;
  148. dst_format = dst->format;
  149. src_trans = pipe_get_transfer(pipe,
  150. src,
  151. src_level,
  152. src_box->z,
  153. PIPE_TRANSFER_READ,
  154. src_box->x, src_box->y, w, h);
  155. dst_trans = pipe_get_transfer(pipe,
  156. dst,
  157. dst_level,
  158. dst_z,
  159. PIPE_TRANSFER_WRITE,
  160. dst_x, dst_y, w, h);
  161. assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format));
  162. assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format));
  163. assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format));
  164. src_map = pipe->transfer_map(pipe, src_trans);
  165. dst_map = pipe->transfer_map(pipe, dst_trans);
  166. assert(src_map);
  167. assert(dst_map);
  168. if (src_map && dst_map) {
  169. if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
  170. memcpy(dst_map, src_map, w);
  171. } else {
  172. util_copy_rect(dst_map,
  173. dst_format,
  174. dst_trans->stride,
  175. 0, 0,
  176. w, h,
  177. src_map,
  178. src_trans->stride,
  179. 0,
  180. 0);
  181. }
  182. }
  183. pipe->transfer_unmap(pipe, src_trans);
  184. pipe->transfer_unmap(pipe, dst_trans);
  185. pipe->transfer_destroy(pipe, src_trans);
  186. pipe->transfer_destroy(pipe, dst_trans);
  187. }
  188. #define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
  189. /**
  190. * Fallback for pipe->clear_render_target() function.
  191. * XXX this looks too hackish to be really useful.
  192. * cpp > 4 looks like a gross hack at best...
  193. * Plus can't use these transfer fallbacks when clearing
  194. * multisampled surfaces for instance.
  195. */
  196. void
  197. util_clear_render_target(struct pipe_context *pipe,
  198. struct pipe_surface *dst,
  199. const float *rgba,
  200. unsigned dstx, unsigned dsty,
  201. unsigned width, unsigned height)
  202. {
  203. struct pipe_transfer *dst_trans;
  204. void *dst_map;
  205. union util_color uc;
  206. assert(dst->texture);
  207. if (!dst->texture)
  208. return;
  209. /* XXX: should handle multiple layers */
  210. dst_trans = pipe_get_transfer(pipe,
  211. dst->texture,
  212. dst->u.tex.level,
  213. dst->u.tex.first_layer,
  214. PIPE_TRANSFER_WRITE,
  215. dstx, dsty, width, height);
  216. dst_map = pipe->transfer_map(pipe, dst_trans);
  217. assert(dst_map);
  218. if (dst_map) {
  219. assert(dst_trans->stride > 0);
  220. util_pack_color(rgba, dst->texture->format, &uc);
  221. util_fill_rect(dst_map, dst->texture->format,
  222. dst_trans->stride,
  223. 0, 0, width, height, &uc);
  224. }
  225. pipe->transfer_unmap(pipe, dst_trans);
  226. pipe->transfer_destroy(pipe, dst_trans);
  227. }
  228. /**
  229. * Fallback for pipe->clear_stencil() function.
  230. * sw fallback doesn't look terribly useful here.
  231. * Plus can't use these transfer fallbacks when clearing
  232. * multisampled surfaces for instance.
  233. */
  234. void
  235. util_clear_depth_stencil(struct pipe_context *pipe,
  236. struct pipe_surface *dst,
  237. unsigned clear_flags,
  238. double depth,
  239. unsigned stencil,
  240. unsigned dstx, unsigned dsty,
  241. unsigned width, unsigned height)
  242. {
  243. struct pipe_transfer *dst_trans;
  244. ubyte *dst_map;
  245. boolean need_rmw = FALSE;
  246. if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) &&
  247. ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
  248. util_format_is_depth_and_stencil(dst->format))
  249. need_rmw = TRUE;
  250. assert(dst->texture);
  251. if (!dst->texture)
  252. return;
  253. dst_trans = pipe_get_transfer(pipe,
  254. dst->texture,
  255. dst->u.tex.level,
  256. dst->u.tex.first_layer,
  257. (need_rmw ? PIPE_TRANSFER_READ_WRITE :
  258. PIPE_TRANSFER_WRITE),
  259. dstx, dsty, width, height);
  260. dst_map = pipe->transfer_map(pipe, dst_trans);
  261. assert(dst_map);
  262. if (dst_map) {
  263. unsigned dst_stride = dst_trans->stride;
  264. unsigned zstencil = util_pack_z_stencil(dst->texture->format, depth, stencil);
  265. unsigned i, j;
  266. assert(dst_trans->stride > 0);
  267. switch (util_format_get_blocksize(dst->format)) {
  268. case 1:
  269. assert(dst->format == PIPE_FORMAT_S8_USCALED);
  270. if(dst_stride == width)
  271. memset(dst_map, (ubyte) zstencil, height * width);
  272. else {
  273. for (i = 0; i < height; i++) {
  274. memset(dst_map, (ubyte) zstencil, width);
  275. dst_map += dst_stride;
  276. }
  277. }
  278. break;
  279. case 2:
  280. assert(dst->format == PIPE_FORMAT_Z16_UNORM);
  281. for (i = 0; i < height; i++) {
  282. uint16_t *row = (uint16_t *)dst_map;
  283. for (j = 0; j < width; j++)
  284. *row++ = (uint16_t) zstencil;
  285. dst_map += dst_stride;
  286. }
  287. break;
  288. case 4:
  289. if (!need_rmw) {
  290. for (i = 0; i < height; i++) {
  291. uint32_t *row = (uint32_t *)dst_map;
  292. for (j = 0; j < width; j++)
  293. *row++ = zstencil;
  294. dst_map += dst_stride;
  295. }
  296. }
  297. else {
  298. uint32_t dst_mask;
  299. if (dst->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED)
  300. dst_mask = 0xffffff00;
  301. else {
  302. assert(dst->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM);
  303. dst_mask = 0xffffff;
  304. }
  305. if (clear_flags & PIPE_CLEAR_DEPTH)
  306. dst_mask = ~dst_mask;
  307. for (i = 0; i < height; i++) {
  308. uint32_t *row = (uint32_t *)dst_map;
  309. for (j = 0; j < width; j++) {
  310. uint32_t tmp = *row & dst_mask;
  311. *row++ = tmp | (zstencil & ~dst_mask);
  312. }
  313. dst_map += dst_stride;
  314. }
  315. }
  316. break;
  317. case 8:
  318. {
  319. uint64_t zstencil = util_pack64_z_stencil(dst->texture->format,
  320. depth, stencil);
  321. assert(dst->format == PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED);
  322. if (!need_rmw) {
  323. for (i = 0; i < height; i++) {
  324. uint64_t *row = (uint64_t *)dst_map;
  325. for (j = 0; j < width; j++)
  326. *row++ = zstencil;
  327. dst_map += dst_stride;
  328. }
  329. }
  330. else {
  331. uint64_t src_mask;
  332. if (clear_flags & PIPE_CLEAR_DEPTH)
  333. src_mask = 0x00000000ffffffffull;
  334. else
  335. src_mask = 0x000000ff00000000ull;
  336. for (i = 0; i < height; i++) {
  337. uint64_t *row = (uint64_t *)dst_map;
  338. for (j = 0; j < width; j++) {
  339. uint64_t tmp = *row & ~src_mask;
  340. *row++ = tmp | (zstencil & src_mask);
  341. }
  342. dst_map += dst_stride;
  343. }
  344. }
  345. break;
  346. }
  347. default:
  348. assert(0);
  349. break;
  350. }
  351. }
  352. pipe->transfer_unmap(pipe, dst_trans);
  353. pipe->transfer_destroy(pipe, dst_trans);
  354. }