Move compiler.h and imports.h/c from src/mesa/main into src/util
[mesa.git] / src / mesa / drivers / dri / i965 / intel_upload.c
index ec3109bd4411d01bc4c530556cf4918e9d51accb..595e330f3b6e589152549866aa5d78c2a9f415af 100644 (file)
  * Batched upload via BOs.
  */
 
-#include "main/imports.h"
-#include "main/mtypes.h"
+#include "util/imports.h"
 #include "main/macros.h"
-#include "main/bufferobj.h"
-
+#include "brw_bufmgr.h"
 #include "brw_context.h"
-#include "intel_blit.h"
 #include "intel_buffer_objects.h"
-#include "intel_batchbuffer.h"
-#include "intel_fbo.h"
-#include "intel_mipmap_tree.h"
-#include "intel_regions.h"
-
-#include "brw_context.h"
-
-#define INTEL_UPLOAD_SIZE (64*1024)
-
-/**
- * Like ALIGN(), but works with a non-power-of-two alignment.
- */
-#define ALIGN_NPOT(value, alignment) \
-   (((value) + (alignment) - 1) / (alignment) * (alignment))
 
 void
-intel_upload_finish(struct brw_context *brw)
+brw_upload_finish(struct brw_uploader *upload)
 {
-   if (!brw->upload.bo)
+   assert((upload->bo == NULL) == (upload->map == NULL));
+   if (!upload->bo)
       return;
 
-   if (brw->upload.buffer_len) {
-      drm_intel_bo_subdata(brw->upload.bo,
-                           brw->upload.buffer_offset,
-                           brw->upload.buffer_len,
-                           brw->upload.buffer);
-      brw->upload.buffer_len = 0;
-   }
-
-   drm_intel_bo_unreference(brw->upload.bo);
-   brw->upload.bo = NULL;
+   brw_bo_unmap(upload->bo);
+   brw_bo_unreference(upload->bo);
+   upload->bo = NULL;
+   upload->map = NULL;
+   upload->next_offset = 0;
 }
 
-static void
-wrap_buffers(struct brw_context *brw, GLuint size)
-{
-   intel_upload_finish(brw);
-
-   if (size < INTEL_UPLOAD_SIZE)
-      size = INTEL_UPLOAD_SIZE;
-
-   brw->upload.bo = drm_intel_bo_alloc(brw->bufmgr, "upload", size, 0);
-   brw->upload.offset = 0;
-}
-
-void
-intel_upload_data(struct brw_context *brw,
-                  const void *ptr, GLuint size, GLuint align,
-                  drm_intel_bo **return_bo,
-                  GLuint *return_offset)
+/**
+ * Interface for getting memory for uploading streamed data to the GPU
+ *
+ * In most cases, streamed data (for GPU state structures, for example) is
+ * uploaded through brw_state_batch(), since that interface allows relocations
+ * from the streamed space returned to other BOs.  However, that interface has
+ * the restriction that the amount of space allocated has to be "small".
+ *
+ * This interface, on the other hand, is able to handle arbitrary sized
+ * allocation requests, though it will batch small allocations into the same
+ * BO for efficiency and reduced memory footprint.
+ *
+ * \note The returned pointer is valid only until brw_upload_finish().
+ *
+ * \param out_bo Pointer to a BO, which must point to a valid BO or NULL on
+ * entry, and will have a reference to the new BO containing the state on
+ * return.
+ *
+ * \param out_offset Offset within the buffer object that the data will land.
+ */
+void *
+brw_upload_space(struct brw_uploader *upload,
+                 uint32_t size,
+                 uint32_t alignment,
+                 struct brw_bo **out_bo,
+                 uint32_t *out_offset)
 {
-   GLuint base, delta;
+   uint32_t offset;
 
-   base = ALIGN_NPOT(brw->upload.offset, align);
-   if (brw->upload.bo == NULL || base + size > brw->upload.bo->size) {
-      wrap_buffers(brw, size);
-      base = 0;
+   offset = ALIGN_NPOT(upload->next_offset, alignment);
+   if (upload->bo && offset + size > upload->bo->size) {
+      brw_upload_finish(upload);
+      offset = 0;
    }
 
-   drm_intel_bo_reference(brw->upload.bo);
-   *return_bo = brw->upload.bo;
-   *return_offset = base;
-
-   delta = base - brw->upload.offset;
-   if (brw->upload.buffer_len &&
-       brw->upload.buffer_len + delta + size > sizeof(brw->upload.buffer)) {
-      drm_intel_bo_subdata(brw->upload.bo,
-                           brw->upload.buffer_offset,
-                           brw->upload.buffer_len,
-                           brw->upload.buffer);
-      brw->upload.buffer_len = 0;
+   assert((upload->bo == NULL) == (upload->map == NULL));
+   if (!upload->bo) {
+      upload->bo = brw_bo_alloc(upload->bufmgr, "streamed data",
+                                MAX2(upload->default_size, size),
+                                BRW_MEMZONE_OTHER);
+      upload->map = brw_bo_map(NULL, upload->bo,
+                               MAP_READ | MAP_WRITE |
+                               MAP_PERSISTENT | MAP_ASYNC);
    }
 
-   if (size < sizeof(brw->upload.buffer)) {
-      if (brw->upload.buffer_len == 0)
-         brw->upload.buffer_offset = base;
-      else
-         brw->upload.buffer_len += delta;
+   upload->next_offset = offset + size;
 
-      memcpy(brw->upload.buffer + brw->upload.buffer_len, ptr, size);
-      brw->upload.buffer_len += size;
-   } else {
-      drm_intel_bo_subdata(brw->upload.bo, base, size, ptr);
+   *out_offset = offset;
+   if (*out_bo != upload->bo) {
+      brw_bo_unreference(*out_bo);
+      *out_bo = upload->bo;
+      brw_bo_reference(upload->bo);
    }
 
-   brw->upload.offset = base + size;
+   return upload->map + offset;
 }
 
-void *
-intel_upload_map(struct brw_context *brw, GLuint size, GLuint align)
+/**
+ * Handy interface to upload some data to temporary GPU memory quickly.
+ *
+ * References to this memory should not be retained across batch flushes.
+ */
+void
+brw_upload_data(struct brw_uploader *upload,
+                const void *data,
+                uint32_t size,
+                uint32_t alignment,
+                struct brw_bo **out_bo,
+                uint32_t *out_offset)
 {
-   GLuint base, delta;
-   char *ptr;
-
-   base = ALIGN_NPOT(brw->upload.offset, align);
-   if (brw->upload.bo == NULL || base + size > brw->upload.bo->size) {
-      wrap_buffers(brw, size);
-      base = 0;
-   }
-
-   delta = base - brw->upload.offset;
-   if (brw->upload.buffer_len &&
-       brw->upload.buffer_len + delta + size > sizeof(brw->upload.buffer)) {
-      drm_intel_bo_subdata(brw->upload.bo,
-                           brw->upload.buffer_offset,
-                           brw->upload.buffer_len,
-                           brw->upload.buffer);
-      brw->upload.buffer_len = 0;
-   }
-
-   if (size <= sizeof(brw->upload.buffer)) {
-      if (brw->upload.buffer_len == 0)
-         brw->upload.buffer_offset = base;
-      else
-         brw->upload.buffer_len += delta;
-
-      ptr = brw->upload.buffer + brw->upload.buffer_len;
-      brw->upload.buffer_len += size;
-   } else {
-      ptr = malloc(size);
-   }
-
-   return ptr;
+   void *dst = brw_upload_space(upload, size, alignment, out_bo, out_offset);
+   memcpy(dst, data, size);
 }
 
 void
-intel_upload_unmap(struct brw_context *brw,
-                   const void *ptr, GLuint size, GLuint align,
-                   drm_intel_bo **return_bo,
-                   GLuint *return_offset)
+brw_upload_init(struct brw_uploader *upload,
+                struct brw_bufmgr *bufmgr,
+                unsigned default_size)
 {
-   GLuint base;
-
-   base = ALIGN_NPOT(brw->upload.offset, align);
-   if (size > sizeof(brw->upload.buffer)) {
-      drm_intel_bo_subdata(brw->upload.bo, base, size, ptr);
-      free((void*)ptr);
-   }
-
-   drm_intel_bo_reference(brw->upload.bo);
-   *return_bo = brw->upload.bo;
-   *return_offset = base;
-
-   brw->upload.offset = base + size;
+   upload->bufmgr = bufmgr;
+   upload->bo = NULL;
+   upload->map = NULL;
+   upload->next_offset = 0;
+   upload->default_size = default_size;
 }