<commit_before>/*
 * Mesa 3-D graphics library
 *
 * Copyright (C) 2012-2013 LunarG, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Authors:
 *    <NAME> <<EMAIL>>
 */

#include "util/u_surface.h"
#include "util/u_transfer.h"
#include "util/u_format_etc.h"

#include "ilo_cp.h"
#include "ilo_context.h"
#include "ilo_resource.h"
#include "ilo_transfer.h"

enum ilo_transfer_map_method {
   ILO_TRANSFER_MAP_DIRECT,
   ILO_TRANSFER_MAP_STAGING_SYS,
};

struct ilo_transfer {
   struct pipe_transfer base;

   enum ilo_transfer_map_method method;
   void *ptr;

   void *staging_sys;
};

static inline struct ilo_transfer *
ilo_transfer(struct pipe_transfer *transfer)
{
   return (struct ilo_transfer *) transfer;
}

/**
 * Choose the best mapping method, depending on the transfer usage and whether
 * the bo is busy.
 */
static bool
choose_transfer_method(struct ilo_context *ilo, struct ilo_transfer *xfer)
{
   struct pipe_resource *res = xfer->base.resource;
   struct ilo_texture *tex;
   struct ilo_buffer *buf;
   struct intel_bo *bo;
   bool will_be_busy, will_stall;

   if (res->target == PIPE_BUFFER) {
      tex = NULL;

      buf = ilo_buffer(res);
      bo = buf->bo;
   }
   else {
      buf = NULL;

      tex = ilo_texture(res);
      bo = tex->bo;

      if (!(xfer->base.usage & PIPE_TRANSFER_MAP_DIRECTLY)) {
         /* need to convert on-the-fly */
         if (tex->bo_format != tex->base.format) {
            xfer->method = ILO_TRANSFER_MAP_STAGING_SYS;
            return true;
         }
      }
   }

   xfer->method = ILO_TRANSFER_MAP_DIRECT;

   /* unsynchronized map does not stall */
   if (xfer->base.usage & PIPE_TRANSFER_UNSYNCHRONIZED)
      return true;

   will_be_busy = ilo->cp->bo->references(ilo->cp->bo, bo);
   if (!will_be_busy) {
      /*
       * XXX With hardware context support, the bo may be needed by GPU
       * without being referenced by ilo->cp->bo.  We have to flush
       * unconditionally, and that is bad.
       */
      if (ilo->cp->hw_ctx)
         ilo_cp_flush(ilo->cp);

      if (!intel_bo_is_busy(bo))
         return true;
   }

   /* bo is busy and mapping it will stall */
   will_stall = true;

   if (xfer->base.usage & PIPE_TRANSFER_MAP_DIRECTLY) {
      /* nothing we can do */
   }
   else if (xfer->base.usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
      /* discard old bo and allocate a new one for mapping */
      if ((tex && ilo_texture_alloc_bo(tex)) ||
          (buf && ilo_buffer_alloc_bo(buf)))
         will_stall = false;
   }
   else if (xfer->base.usage & PIPE_TRANSFER_FLUSH_EXPLICIT) {
      /*
       * We could allocate and return a system buffer here.  When a region of
       * the buffer is explicitly flushed, we pwrite() the region to a
       * temporary bo and emit pipelined copy blit.
       *
       * For now, do nothing.
       */
   }
   else if (xfer->base.usage & PIPE_TRANSFER_DISCARD_RANGE) {
      /*
       * We could allocate a temporary bo for mapping, and emit pipelined copy
       * blit upon unmapping.
       *
       * For now, do nothing.
       */
   }

   if (will_stall) {
      if (xfer->base.usage & PIPE_TRANSFER_DONTBLOCK)
         return false;

      /* flush to make bo busy (so that map() stalls as it should be) */
      if (will_be_busy)
         ilo_cp_flush(ilo->cp);
   }

   return true;
}

static void
tex_staging_sys_convert_write(enum pipe_format dst_fmt,
                              const struct pipe_transfer *dst_xfer,
                              void *dst,
                              enum pipe_format src_fmt,
                              const struct pipe_transfer *src_xfer,
                              const void *src)
{
   int i;

   switch (src_fmt) {
   case PIPE_FORMAT_ETC1_RGB8:
      assert(dst_fmt == PIPE_FORMAT_R8G8B8X8_UNORM);

      for (i = 0; i < dst_xfer->box.depth; i++) {
         util_format_etc1_rgb8_unpack_rgba_8unorm(dst,
               dst_xfer->stride, src, src_xfer->stride,
               dst_xfer->box.width, dst_xfer->box.height);

         dst += dst_xfer->layer_stride;
         src += src_xfer->layer_stride;
      }
      break;
   default:
      assert(!"unable to convert the staging data");
      break;
   }
}

static void
tex_staging_sys_unmap(struct ilo_context *ilo,
                      struct ilo_texture *tex,
                      struct ilo_transfer *xfer)
{
   const void *src = xfer->ptr;
   struct pipe_transfer *dst_xfer;
   void *dst;

   dst = ilo->base.transfer_map(&ilo->base,
         xfer->base.resource, xfer->base.level,
         PIPE_TRANSFER_WRITE |
         PIPE_TRANSFER_MAP_DIRECTLY |
         PIPE_TRANSFER_DISCARD_RANGE,
         &xfer->base.box, &dst_xfer);
   if (!dst_xfer) {
      ilo_err("failed to map resource for moving staging data\n");
      FREE(xfer->staging_sys);
      return;
   }

   if (likely(tex->bo_format != tex->base.format)) {
      tex_staging_sys_convert_write(tex->bo_format, dst_xfer, dst,
            tex->base.format, &xfer->base, src);
   }
   else {
      util_copy_box(dst, tex->bo_format,
            dst_xfer->stride, dst_xfer->layer_stride, 0, 0, 0,
            dst_xfer->box.width, dst_xfer->box.height, dst_xfer->box.depth,
            src, xfer->base.stride, xfer->base.layer_stride, 0, 0, 0);
   }

   ilo->base.transfer_unmap(&ilo->base, dst_xfer);<commit_msg>ilo: no writeback without PIPE_TRANSFER_WRITE<commit_after>/*
 * Mesa 3-D graphics library
 *
 * Copyright (C) 2012-2013 LunarG, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Authors:
 *    <NAME> <<EMAIL>>
 */

#include "util/u_surface.h"
#include "util/u_transfer.h"
#include "util/u_format_etc.h"

#include "ilo_cp.h"
#include "ilo_context.h"
#include "ilo_resource.h"
#include "ilo_transfer.h"

enum ilo_transfer_map_method {
   ILO_TRANSFER_MAP_DIRECT,
   ILO_TRANSFER_MAP_STAGING_SYS,
};

struct ilo_transfer {
   struct pipe_transfer base;

   enum ilo_transfer_map_method method;
   void *ptr;

   void *staging_sys;
};

static inline struct ilo_transfer *
ilo_transfer(struct pipe_transfer *transfer)
{
   return (struct ilo_transfer *) transfer;
}

/**
 * Choose the best mapping method, depending on the transfer usage and whether
 * the bo is busy.
 */
static bool
choose_transfer_method(struct ilo_context *ilo, struct ilo_transfer *xfer)
{
   struct pipe_resource *res = xfer->base.resource;
   struct ilo_texture *tex;
   struct ilo_buffer *buf;
   struct intel_bo *bo;
   bool will_be_busy, will_stall;

   if (res->target == PIPE_BUFFER) {
      tex = NULL;

      buf = ilo_buffer(res);
      bo = buf->bo;
   }
   else {
      buf = NULL;

      tex = ilo_texture(res);
      bo = tex->bo;

      if (!(xfer->base.usage & PIPE_TRANSFER_MAP_DIRECTLY)) {
         /* need to convert on-the-fly */
         if (tex->bo_format != tex->base.format) {
            xfer->method = ILO_TRANSFER_MAP_STAGING_SYS;
            return true;
         }
      }
   }

   xfer->method = ILO_TRANSFER_MAP_DIRECT;

   /* unsynchronized map does not stall */
   if (xfer->base.usage & PIPE_TRANSFER_UNSYNCHRONIZED)
      return true;

   will_be_busy = ilo->cp->bo->references(ilo->cp->bo, bo);
   if (!will_be_busy) {
      /*
       * XXX With hardware context support, the bo may be needed by GPU
       * without being referenced by ilo->cp->bo.  We have to flush
       * unconditionally, and that is bad.
       */
      if (ilo->cp->hw_ctx)
         ilo_cp_flush(ilo->cp);

      if (!intel_bo_is_busy(bo))
         return true;
   }

   /* bo is busy and mapping it will stall */
   will_stall = true;

   if (xfer->base.usage & PIPE_TRANSFER_MAP_DIRECTLY) {
      /* nothing we can do */
   }
   else if (xfer->base.usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
      /* discard old bo and allocate a new one for mapping */
      if ((tex && ilo_texture_alloc_bo(tex)) ||
          (buf && ilo_buffer_alloc_bo(buf)))
         will_stall = false;
   }
   else if (xfer->base.usage & PIPE_TRANSFER_FLUSH_EXPLICIT) {
      /*
       * We could allocate and return a system buffer here.  When a region of
       * the buffer is explicitly flushed, we pwrite() the region to a
       * temporary bo and emit pipelined copy blit.
       *
       * For now, do nothing.
       */
   }
   else if (xfer->base.usage & PIPE_TRANSFER_DISCARD_RANGE) {
      /*
       * We could allocate a temporary bo for mapping, and emit pipelined copy
       * blit upon unmapping.
       *
       * For now, do nothing.
       */
   }

   if (will_stall) {
      if (xfer->base.usage & PIPE_TRANSFER_DONTBLOCK)
         return false;

      /* flush to make bo busy (so that map() stalls as it should be) */
      if (will_be_busy)
         ilo_cp_flush(ilo->cp);
   }

   return true;
}

static void
tex_staging_sys_convert_write(enum pipe_format dst_fmt,
                              const struct pipe_transfer *dst_xfer,
                              void *dst,
                              enum pipe_format src_fmt,
                              const struct pipe_transfer *src_xfer,
                              const void *src)
{
   int i;

   switch (src_fmt) {
   case PIPE_FORMAT_ETC1_RGB8:
      assert(dst_fmt == PIPE_FORMAT_R8G8B8X8_UNORM);

      for (i = 0; i < dst_xfer->box.depth; i++) {
         util_format_etc1_rgb8_unpack_rgba_8unorm(dst,
               dst_xfer->stride, src, src_xfer->stride,
               dst_xfer->box.width, dst_xfer->box.height);

         dst += dst_xfer->layer_stride;
         src += src_xfer->layer_stride;
      }
      break;
   default:
      assert(!"unable to convert the staging data");
      break;
   }
}

static void
tex_staging_sys_unmap(struct ilo_context *ilo,
                      struct ilo_texture *tex,
                      struct ilo_transfer *xfer)
{
   const void *src = xfer->ptr;
   struct pipe_transfer *dst_xfer;
   void *dst;

   if (!(xfer->base.usage & PIPE_TRANSFER_WRITE)) {
      FREE(xfer->staging_sys);
      return;
   }

   dst = ilo->base.transfer_map(&ilo->base,
         xfer->base.resource, xfer->base.level,
         PIPE_TRANSFER_WRITE |
         PIPE_TRANSFER_MAP_DIRECTLY |
         PIPE_TRANSFER_DISCARD_RANGE,
         &xfer->base.box, &dst_xfer);
   if (!dst_xfer) {
      ilo_err("failed to map resource for moving staging data\n");
      FREE(xfer->staging_sys);
      return;
   }

   if (likely(tex->bo_format != tex->base.format)) {
      tex_staging_sys_convert_write(tex->bo_format, dst_xfer, dst,
            tex->base.format, &xfer->base, src);
   }
   else {
      util_copy_box(dst, tex->bo_format,
            dst_xfer->stride, dst_xfer->layer_stride, 0, 0, 0,
            dst_xfer->box.width, dst_xfer->box.height, dst_xfer->box.depth,
            src, xfer->base.stride, xfer->base.layer_stride, 0, 0, 0);
   }

   ilo->base.transfer_unmap(&ilo->base, dst_xfer);
{'fraction_non_alphanumeric': 0.09884217887947781, 'fraction_numerical': 0.0038853057735643796, 'mean_word_length': 2.5308641975308643, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 121, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5310338', 'n_tokens_mistral': 4277, 'n_tokens_neox': 4169, 'n_words': 1176}