i965/tiled_memcopy: Get rid of the direction parameter to get_memcpy
[mesa.git] / src / mesa / drivers / dri / i965 / intel_tex_image.c
1
2 #include "main/macros.h"
3 #include "main/mtypes.h"
4 #include "main/enums.h"
5 #include "main/bufferobj.h"
6 #include "main/context.h"
7 #include "main/formats.h"
8 #include "main/image.h"
9 #include "main/pbo.h"
10 #include "main/renderbuffer.h"
11 #include "main/texcompress.h"
12 #include "main/texgetimage.h"
13 #include "main/texobj.h"
14 #include "main/teximage.h"
15 #include "main/texstore.h"
16
17 #include "drivers/common/meta.h"
18
19 #include "intel_mipmap_tree.h"
20 #include "intel_buffer_objects.h"
21 #include "intel_batchbuffer.h"
22 #include "intel_tex.h"
23 #include "intel_blit.h"
24 #include "intel_fbo.h"
25 #include "intel_image.h"
26 #include "intel_tiled_memcpy.h"
27 #include "brw_context.h"
28
29 #define FILE_DEBUG_FLAG DEBUG_TEXTURE
30
31 /* Work back from the specified level of the image to the baselevel and create a
32 * miptree of that size.
33 */
34 struct intel_mipmap_tree *
35 intel_miptree_create_for_teximage(struct brw_context *brw,
36 struct intel_texture_object *intelObj,
37 struct intel_texture_image *intelImage,
38 uint32_t layout_flags)
39 {
40 GLuint lastLevel;
41 int width, height, depth;
42 GLuint i;
43
44 intel_get_image_dims(&intelImage->base.Base, &width, &height, &depth);
45
46 DBG("%s\n", __func__);
47
48 /* Figure out image dimensions at start level. */
49 for (i = intelImage->base.Base.Level; i > 0; i--) {
50 width <<= 1;
51 if (height != 1)
52 height <<= 1;
53 if (intelObj->base.Target == GL_TEXTURE_3D)
54 depth <<= 1;
55 }
56
57 /* Guess a reasonable value for lastLevel. This is probably going
58 * to be wrong fairly often and might mean that we have to look at
59 * resizable buffers, or require that buffers implement lazy
60 * pagetable arrangements.
61 */
62 if ((intelObj->base.Sampler.MinFilter == GL_NEAREST ||
63 intelObj->base.Sampler.MinFilter == GL_LINEAR) &&
64 intelImage->base.Base.Level == 0 &&
65 !intelObj->base.GenerateMipmap) {
66 lastLevel = 0;
67 } else {
68 lastLevel = _mesa_get_tex_max_num_levels(intelObj->base.Target,
69 width, height, depth) - 1;
70 }
71
72 return intel_miptree_create(brw,
73 intelObj->base.Target,
74 intelImage->base.Base.TexFormat,
75 0,
76 lastLevel,
77 width,
78 height,
79 depth,
80 intelImage->base.Base.NumSamples,
81 layout_flags | MIPTREE_LAYOUT_TILING_ANY);
82 }
83
84 static void
85 intelTexImage(struct gl_context * ctx,
86 GLuint dims,
87 struct gl_texture_image *texImage,
88 GLenum format, GLenum type, const void *pixels,
89 const struct gl_pixelstore_attrib *unpack)
90 {
91 struct intel_texture_image *intelImage = intel_texture_image(texImage);
92 bool ok;
93
94 bool tex_busy = intelImage->mt && drm_intel_bo_busy(intelImage->mt->bo);
95
96 DBG("%s mesa_format %s target %s format %s type %s level %d %dx%dx%d\n",
97 __func__, _mesa_get_format_name(texImage->TexFormat),
98 _mesa_enum_to_string(texImage->TexObject->Target),
99 _mesa_enum_to_string(format), _mesa_enum_to_string(type),
100 texImage->Level, texImage->Width, texImage->Height, texImage->Depth);
101
102 /* Allocate storage for texture data. */
103 if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) {
104 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
105 return;
106 }
107
108 assert(intelImage->mt);
109
110 ok = _mesa_meta_pbo_TexSubImage(ctx, dims, texImage, 0, 0, 0,
111 texImage->Width, texImage->Height,
112 texImage->Depth,
113 format, type, pixels,
114 tex_busy, unpack);
115 if (ok)
116 return;
117
118 ok = intel_texsubimage_tiled_memcpy(ctx, dims, texImage,
119 0, 0, 0, /*x,y,z offsets*/
120 texImage->Width,
121 texImage->Height,
122 texImage->Depth,
123 format, type, pixels, unpack,
124 false /*allocate_storage*/);
125 if (ok)
126 return;
127
128 DBG("%s: upload image %dx%dx%d pixels %p\n",
129 __func__, texImage->Width, texImage->Height, texImage->Depth,
130 pixels);
131
132 _mesa_store_teximage(ctx, dims, texImage,
133 format, type, pixels, unpack);
134 }
135
136
137 /**
138 * Binds a BO to a texture image, as if it was uploaded by glTexImage2D().
139 *
140 * Used for GLX_EXT_texture_from_pixmap and EGL image extensions,
141 */
142 static void
143 intel_set_texture_image_bo(struct gl_context *ctx,
144 struct gl_texture_image *image,
145 drm_intel_bo *bo,
146 GLenum target,
147 GLenum internalFormat,
148 mesa_format format,
149 uint32_t offset,
150 GLuint width, GLuint height,
151 GLuint pitch,
152 GLuint tile_x, GLuint tile_y,
153 uint32_t layout_flags)
154 {
155 struct brw_context *brw = brw_context(ctx);
156 struct intel_texture_image *intel_image = intel_texture_image(image);
157 struct gl_texture_object *texobj = image->TexObject;
158 struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
159 uint32_t draw_x, draw_y;
160
161 _mesa_init_teximage_fields(&brw->ctx, image,
162 width, height, 1,
163 0, internalFormat, format);
164
165 ctx->Driver.FreeTextureImageBuffer(ctx, image);
166
167 intel_image->mt = intel_miptree_create_for_bo(brw, bo, image->TexFormat,
168 0, width, height, 1, pitch,
169 layout_flags);
170 if (intel_image->mt == NULL)
171 return;
172 intel_image->mt->target = target;
173 intel_image->mt->total_width = width;
174 intel_image->mt->total_height = height;
175 intel_image->mt->level[0].slice[0].x_offset = tile_x;
176 intel_image->mt->level[0].slice[0].y_offset = tile_y;
177
178 intel_miptree_get_tile_offsets(intel_image->mt, 0, 0, &draw_x, &draw_y);
179
180 /* From "OES_EGL_image" error reporting. We report GL_INVALID_OPERATION
181 * for EGL images from non-tile aligned sufaces in gen4 hw and earlier which has
182 * trouble resolving back to destination image due to alignment issues.
183 */
184 if (!brw->has_surface_tile_offset &&
185 (draw_x != 0 || draw_y != 0)) {
186 _mesa_error(ctx, GL_INVALID_OPERATION, __func__);
187 intel_miptree_release(&intel_image->mt);
188 return;
189 }
190
191 intel_texobj->needs_validate = true;
192
193 intel_image->mt->offset = offset;
194 assert(pitch % intel_image->mt->cpp == 0);
195 intel_image->base.RowStride = pitch / intel_image->mt->cpp;
196
197 /* Immediately validate the image to the object. */
198 intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
199 }
200
201 void
202 intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
203 GLint texture_format,
204 __DRIdrawable *dPriv)
205 {
206 struct gl_framebuffer *fb = dPriv->driverPrivate;
207 struct brw_context *brw = pDRICtx->driverPrivate;
208 struct gl_context *ctx = &brw->ctx;
209 struct intel_renderbuffer *rb;
210 struct gl_texture_object *texObj;
211 struct gl_texture_image *texImage;
212 int level = 0, internalFormat = 0;
213 mesa_format texFormat = MESA_FORMAT_NONE;
214
215 texObj = _mesa_get_current_tex_object(ctx, target);
216
217 if (!texObj)
218 return;
219
220 if (dPriv->lastStamp != dPriv->dri2.stamp ||
221 !pDRICtx->driScreenPriv->dri2.useInvalidate)
222 intel_update_renderbuffers(pDRICtx, dPriv);
223
224 rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
225 /* If the miptree isn't set, then intel_update_renderbuffers was unable
226 * to get the BO for the drawable from the window system.
227 */
228 if (!rb || !rb->mt)
229 return;
230
231 if (rb->mt->cpp == 4) {
232 if (texture_format == __DRI_TEXTURE_FORMAT_RGB) {
233 internalFormat = GL_RGB;
234 texFormat = MESA_FORMAT_B8G8R8X8_UNORM;
235 }
236 else {
237 internalFormat = GL_RGBA;
238 texFormat = MESA_FORMAT_B8G8R8A8_UNORM;
239 }
240 } else if (rb->mt->cpp == 2) {
241 internalFormat = GL_RGB;
242 texFormat = MESA_FORMAT_B5G6R5_UNORM;
243 }
244
245 _mesa_lock_texture(&brw->ctx, texObj);
246 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
247 intel_miptree_make_shareable(brw, rb->mt);
248 intel_set_texture_image_bo(ctx, texImage, rb->mt->bo, target,
249 internalFormat, texFormat, 0,
250 rb->Base.Base.Width,
251 rb->Base.Base.Height,
252 rb->mt->pitch,
253 0, 0, 0);
254 _mesa_unlock_texture(&brw->ctx, texObj);
255 }
256
257 static GLboolean
258 intel_bind_renderbuffer_tex_image(struct gl_context *ctx,
259 struct gl_renderbuffer *rb,
260 struct gl_texture_image *image)
261 {
262 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
263 struct intel_texture_image *intel_image = intel_texture_image(image);
264 struct gl_texture_object *texobj = image->TexObject;
265 struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
266
267 /* We can only handle RB allocated with AllocRenderbufferStorage, or
268 * window-system renderbuffers.
269 */
270 assert(!rb->TexImage);
271
272 if (!irb->mt)
273 return false;
274
275 _mesa_lock_texture(ctx, texobj);
276 _mesa_init_teximage_fields(ctx, image,
277 rb->Width, rb->Height, 1,
278 0, rb->InternalFormat, rb->Format);
279 image->NumSamples = rb->NumSamples;
280
281 intel_miptree_reference(&intel_image->mt, irb->mt);
282
283 /* Immediately validate the image to the object. */
284 intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
285
286 intel_texobj->needs_validate = true;
287 _mesa_unlock_texture(ctx, texobj);
288
289 return true;
290 }
291
292 void
293 intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
294 {
295 /* The old interface didn't have the format argument, so copy our
296 * implementation's behavior at the time.
297 */
298 intelSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
299 }
300
301 static void
302 intel_image_target_texture_2d(struct gl_context *ctx, GLenum target,
303 struct gl_texture_object *texObj,
304 struct gl_texture_image *texImage,
305 GLeglImageOES image_handle)
306 {
307 struct brw_context *brw = brw_context(ctx);
308 __DRIscreen *screen;
309 __DRIimage *image;
310
311 screen = brw->intelScreen->driScrnPriv;
312 image = screen->dri2.image->lookupEGLImage(screen, image_handle,
313 screen->loaderPrivate);
314 if (image == NULL)
315 return;
316
317 /* We support external textures only for EGLImages created with
318 * EGL_EXT_image_dma_buf_import. We may lift that restriction in the future.
319 */
320 if (target == GL_TEXTURE_EXTERNAL_OES && !image->dma_buf_imported) {
321 _mesa_error(ctx, GL_INVALID_OPERATION,
322 "glEGLImageTargetTexture2DOES(external target is enabled only "
323 "for images created with EGL_EXT_image_dma_buf_import");
324 return;
325 }
326
327 /* Disallow depth/stencil textures: we don't have a way to pass the
328 * separate stencil miptree of a GL_DEPTH_STENCIL texture through.
329 */
330 if (image->has_depthstencil) {
331 _mesa_error(ctx, GL_INVALID_OPERATION, __func__);
332 return;
333 }
334
335 /* Disable creation of the texture's aux buffers because the driver exposes
336 * no EGL API to manage them. That is, there is no API for resolving the aux
337 * buffer's content to the main buffer nor for invalidating the aux buffer's
338 * content.
339 */
340 intel_set_texture_image_bo(ctx, texImage, image->bo,
341 target, image->internal_format,
342 image->format, image->offset,
343 image->width, image->height,
344 image->pitch,
345 image->tile_x, image->tile_y,
346 MIPTREE_LAYOUT_DISABLE_AUX);
347 }
348
349 /**
350 * \brief A fast path for glGetTexImage.
351 *
352 * \see intel_readpixels_tiled_memcpy()
353 */
354 bool
355 intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
356 struct gl_texture_image *texImage,
357 GLint xoffset, GLint yoffset,
358 GLsizei width, GLsizei height,
359 GLenum format, GLenum type,
360 GLvoid *pixels,
361 const struct gl_pixelstore_attrib *packing)
362 {
363 struct brw_context *brw = brw_context(ctx);
364 struct intel_texture_image *image = intel_texture_image(texImage);
365 int dst_pitch;
366
367 /* The miptree's buffer. */
368 drm_intel_bo *bo;
369
370 int error = 0;
371
372 uint32_t cpp;
373 mem_copy_fn mem_copy = NULL;
374
375 /* This fastpath is restricted to specific texture types:
376 * a 2D BGRA, RGBA, L8 or A8 texture. It could be generalized to support
377 * more types.
378 *
379 * FINISHME: The restrictions below on packing alignment and packing row
380 * length are likely unneeded now because we calculate the destination stride
381 * with _mesa_image_row_stride. However, before removing the restrictions
382 * we need tests.
383 */
384 if (!brw->has_llc ||
385 !(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) ||
386 !(texImage->TexObject->Target == GL_TEXTURE_2D ||
387 texImage->TexObject->Target == GL_TEXTURE_RECTANGLE) ||
388 pixels == NULL ||
389 _mesa_is_bufferobj(packing->BufferObj) ||
390 packing->Alignment > 4 ||
391 packing->SkipPixels > 0 ||
392 packing->SkipRows > 0 ||
393 (packing->RowLength != 0 && packing->RowLength != width) ||
394 packing->SwapBytes ||
395 packing->LsbFirst ||
396 packing->Invert)
397 return false;
398
399 /* We can't handle copying from RGBX or BGRX because the tiled_memcpy
400 * function doesn't set the last channel to 1. Note this checks BaseFormat
401 * rather than TexFormat in case the RGBX format is being simulated with an
402 * RGBA format.
403 */
404 if (texImage->_BaseFormat == GL_RGB)
405 return false;
406
407 if (!intel_get_memcpy(texImage->TexFormat, format, type, &mem_copy, &cpp))
408 return false;
409
410 /* If this is a nontrivial texture view, let another path handle it instead. */
411 if (texImage->TexObject->MinLayer)
412 return false;
413
414 if (!image->mt ||
415 (image->mt->tiling != I915_TILING_X &&
416 image->mt->tiling != I915_TILING_Y)) {
417 /* The algorithm is written only for X- or Y-tiled memory. */
418 return false;
419 }
420
421 /* Since we are going to write raw data to the miptree, we need to resolve
422 * any pending fast color clears before we start.
423 */
424 intel_miptree_resolve_color(brw, image->mt, 0);
425
426 bo = image->mt->bo;
427
428 if (drm_intel_bo_references(brw->batch.bo, bo)) {
429 perf_debug("Flushing before mapping a referenced bo.\n");
430 intel_batchbuffer_flush(brw);
431 }
432
433 error = brw_bo_map(brw, bo, false /* write enable */, "miptree");
434 if (error) {
435 DBG("%s: failed to map bo\n", __func__);
436 return false;
437 }
438
439 dst_pitch = _mesa_image_row_stride(packing, width, format, type);
440
441 DBG("%s: level=%d x,y=(%d,%d) (w,h)=(%d,%d) format=0x%x type=0x%x "
442 "mesa_format=0x%x tiling=%d "
443 "packing=(alignment=%d row_length=%d skip_pixels=%d skip_rows=%d)\n",
444 __func__, texImage->Level, xoffset, yoffset, width, height,
445 format, type, texImage->TexFormat, image->mt->tiling,
446 packing->Alignment, packing->RowLength, packing->SkipPixels,
447 packing->SkipRows);
448
449 int level = texImage->Level + texImage->TexObject->MinLevel;
450
451 /* Adjust x and y offset based on miplevel */
452 xoffset += image->mt->level[level].level_x;
453 yoffset += image->mt->level[level].level_y;
454
455 tiled_to_linear(
456 xoffset * cpp, (xoffset + width) * cpp,
457 yoffset, yoffset + height,
458 pixels - (ptrdiff_t) yoffset * dst_pitch - (ptrdiff_t) xoffset * cpp,
459 bo->virtual,
460 dst_pitch, image->mt->pitch,
461 brw->has_swizzling,
462 image->mt->tiling,
463 mem_copy
464 );
465
466 drm_intel_bo_unmap(bo);
467 return true;
468 }
469
470 static void
471 intel_get_tex_sub_image(struct gl_context *ctx,
472 GLint xoffset, GLint yoffset, GLint zoffset,
473 GLsizei width, GLsizei height, GLint depth,
474 GLenum format, GLenum type, GLvoid *pixels,
475 struct gl_texture_image *texImage)
476 {
477 struct brw_context *brw = brw_context(ctx);
478 bool ok;
479
480 DBG("%s\n", __func__);
481
482 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
483 if (_mesa_meta_pbo_GetTexSubImage(ctx, 3, texImage,
484 xoffset, yoffset, zoffset,
485 width, height, depth, format, type,
486 pixels, &ctx->Pack)) {
487 /* Flush to guarantee coherency between the render cache and other
488 * caches the PBO could potentially be bound to after this point.
489 * See the related comment in intelReadPixels() for a more detailed
490 * explanation.
491 */
492 brw_emit_mi_flush(brw);
493 return;
494 }
495
496 perf_debug("%s: fallback to CPU mapping in PBO case\n", __func__);
497 }
498
499 ok = intel_gettexsubimage_tiled_memcpy(ctx, texImage, xoffset, yoffset,
500 width, height,
501 format, type, pixels, &ctx->Pack);
502
503 if(ok)
504 return;
505
506 _mesa_meta_GetTexSubImage(ctx, xoffset, yoffset, zoffset,
507 width, height, depth,
508 format, type, pixels, texImage);
509
510 DBG("%s - DONE\n", __func__);
511 }
512
513 void
514 intelInitTextureImageFuncs(struct dd_function_table *functions)
515 {
516 functions->TexImage = intelTexImage;
517 functions->EGLImageTargetTexture2D = intel_image_target_texture_2d;
518 functions->BindRenderbufferTexImage = intel_bind_renderbuffer_tex_image;
519 functions->GetTexSubImage = intel_get_tex_sub_image;
520 }