/**
 * Called by vbuf code when we're about to draw something.
 */
static boolean
try_update_scene_state( struct lp_setup_context *setup )
{
   boolean new_scene = (setup->fs.stored == NULL);
   struct lp_scene *scene = setup->scene;

   assert(scene);

   if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) {
      uint8_t *stored;
      unsigned i, j;

      stored = lp_scene_alloc_aligned(scene, 4 * 16, 16);
      if (!stored) {
         assert(!new_scene);
         return FALSE;
      }

      /* smear each blend color component across 16 ubyte elements */
      for (i = 0; i < 4; ++i) {
         uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]);
         for (j = 0; j < 16; ++j)
            stored[i*16 + j] = c;
      }

      setup->blend_color.stored = stored;
      setup->fs.current.jit_context.blend_color = setup->blend_color.stored;
      setup->dirty |= LP_SETUP_NEW_FS;
   }

   if(setup->dirty & LP_SETUP_NEW_CONSTANTS) {
      struct pipe_resource *buffer = setup->constants.current;

      if(buffer) {
         unsigned current_size = buffer->width0;
         const void *current_data = llvmpipe_resource_data(buffer);

         /* TODO: copy only the actually used constants? */

         if(setup->constants.stored_size != current_size ||
            !setup->constants.stored_data ||
            memcmp(setup->constants.stored_data,
                   current_data,
                   current_size) != 0) {
            void *stored;

            stored = lp_scene_alloc(scene, current_size);
            if (!stored) {
               assert(!new_scene);
               return FALSE;
            }

            memcpy(stored,
                   current_data,
                   current_size);
            setup->constants.stored_size = current_size;
            setup->constants.stored_data = stored;
         }
      }
      else {
         setup->constants.stored_size = 0;
         setup->constants.stored_data = NULL;
      }

      setup->fs.current.jit_context.constants = setup->constants.stored_data;
      setup->dirty |= LP_SETUP_NEW_FS;
   }


   if (setup->dirty & LP_SETUP_NEW_FS) {
      if (!setup->fs.stored ||
          memcmp(setup->fs.stored,
                 &setup->fs.current,
                 sizeof setup->fs.current) != 0)
      {
         struct lp_rast_state *stored;
         uint i;
         
         /* The fs state that's been stored in the scene is different from
          * the new, current state.  So allocate a new lp_rast_state object
          * and append it to the bin's setup data buffer.
          */
         stored = (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored);
         if (!stored) {
            assert(!new_scene);
            return FALSE;
         }

         memcpy(stored,
                &setup->fs.current,
                sizeof setup->fs.current);
         setup->fs.stored = stored;
         
         /* The scene now references the textures in the rasterization
          * state record.  Note that now.
          */
         for (i = 0; i < Elements(setup->fs.current_tex); i++) {
            if (setup->fs.current_tex[i]) {
               if (!lp_scene_add_resource_reference(scene,
                                                    setup->fs.current_tex[i],
                                                    new_scene)) {
                  assert(!new_scene);
                  return FALSE;
               }
            }
         }
      }
   }

   if (setup->dirty & LP_SETUP_NEW_SCISSOR) {
      setup->draw_region = setup->framebuffer;
      if (setup->scissor_test) {
         u_rect_possible_intersection(&setup->scissor,
                                      &setup->draw_region);
      }
   }
                                      
   setup->dirty = 0;

   assert(setup->fs.stored);
   return TRUE;
}
Exemple #2
0
/**
 * Called by vbuf code when we're about to draw something.
 *
 * This function stores all dirty state in the current scene's display list
 * memory, via lp_scene_alloc().  We can not pass pointers of mutable state to
 * the JIT functions, as the JIT functions will be called later on, most likely
 * on a different thread.
 *
 * When processing dirty state it is imperative that we don't refer to any
 * pointers previously allocated with lp_scene_alloc() in this function (or any
 * function) as they may belong to a scene freed since then.
 */
static boolean
try_update_scene_state( struct lp_setup_context *setup )
{
   static const float fake_const_buf[4];
   boolean new_scene = (setup->fs.stored == NULL);
   struct lp_scene *scene = setup->scene;
   unsigned i;

   assert(scene);

   if (setup->dirty & LP_SETUP_NEW_VIEWPORTS) {
      /*
       * Record new depth range state for changes due to viewport updates.
       *
       * TODO: Collapse the existing viewport and depth range information
       *       into one structure, for access by JIT.
       */
      struct lp_jit_viewport *stored;

      stored = (struct lp_jit_viewport *)
         lp_scene_alloc(scene, sizeof setup->viewports);

      if (!stored) {
         assert(!new_scene);
         return FALSE;
      }

      memcpy(stored, setup->viewports, sizeof setup->viewports);

      setup->fs.current.jit_context.viewports = stored;
      setup->dirty |= LP_SETUP_NEW_FS;
   }

   if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) {
      uint8_t *stored;
      float* fstored;
      unsigned i, j;
      unsigned size;

      /* Alloc u8_blend_color (16 x i8) and f_blend_color (4 or 8 x f32) */
      size  = 4 * 16 * sizeof(uint8_t);
      size += (LP_MAX_VECTOR_LENGTH / 4) * sizeof(float);
      stored = lp_scene_alloc_aligned(scene, size, LP_MIN_VECTOR_ALIGN);

      if (!stored) {
         assert(!new_scene);
         return FALSE;
      }

      /* Store floating point colour */
      fstored = (float*)(stored + 4*16);
      for (i = 0; i < (LP_MAX_VECTOR_LENGTH / 4); ++i) {
         fstored[i] = setup->blend_color.current.color[i % 4];
      }

      /* smear each blend color component across 16 ubyte elements */
      for (i = 0; i < 4; ++i) {
         uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]);
         for (j = 0; j < 16; ++j)
            stored[i*16 + j] = c;
      }

      setup->blend_color.stored = stored;
      setup->fs.current.jit_context.u8_blend_color = stored;
      setup->fs.current.jit_context.f_blend_color = fstored;
      setup->dirty |= LP_SETUP_NEW_FS;
   }

   if (setup->dirty & LP_SETUP_NEW_CONSTANTS) {
      for (i = 0; i < ARRAY_SIZE(setup->constants); ++i) {
         struct pipe_resource *buffer = setup->constants[i].current.buffer;
         const unsigned current_size = MIN2(setup->constants[i].current.buffer_size,
                                            LP_MAX_TGSI_CONST_BUFFER_SIZE);
         const ubyte *current_data = NULL;
         int num_constants;

         STATIC_ASSERT(DATA_BLOCK_SIZE >= LP_MAX_TGSI_CONST_BUFFER_SIZE);

         if (buffer) {
            /* resource buffer */
            current_data = (ubyte *) llvmpipe_resource_data(buffer);
         }
         else if (setup->constants[i].current.user_buffer) {
            /* user-space buffer */
            current_data = (ubyte *) setup->constants[i].current.user_buffer;
         }

         if (current_data) {
            current_data += setup->constants[i].current.buffer_offset;

            /* TODO: copy only the actually used constants? */

            if (setup->constants[i].stored_size != current_size ||
               !setup->constants[i].stored_data ||
               memcmp(setup->constants[i].stored_data,
                      current_data,
                      current_size) != 0) {
               void *stored;

               stored = lp_scene_alloc(scene, current_size);
               if (!stored) {
                  assert(!new_scene);
                  return FALSE;
               }

               memcpy(stored,
                      current_data,
                      current_size);
               setup->constants[i].stored_size = current_size;
               setup->constants[i].stored_data = stored;
            }
            setup->fs.current.jit_context.constants[i] =
               setup->constants[i].stored_data;
         }
         else {
            setup->constants[i].stored_size = 0;
            setup->constants[i].stored_data = NULL;
            setup->fs.current.jit_context.constants[i] = fake_const_buf;
         }

         num_constants =
            setup->constants[i].stored_size / (sizeof(float) * 4);
         setup->fs.current.jit_context.num_constants[i] = num_constants;
         setup->dirty |= LP_SETUP_NEW_FS;
      }
   }


   if (setup->dirty & LP_SETUP_NEW_FS) {
      if (!setup->fs.stored ||
          memcmp(setup->fs.stored,
                 &setup->fs.current,
                 sizeof setup->fs.current) != 0)
      {
         struct lp_rast_state *stored;
         
         /* The fs state that's been stored in the scene is different from
          * the new, current state.  So allocate a new lp_rast_state object
          * and append it to the bin's setup data buffer.
          */
         stored = (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored);
         if (!stored) {
            assert(!new_scene);
            return FALSE;
         }

         memcpy(stored,
                &setup->fs.current,
                sizeof setup->fs.current);
         setup->fs.stored = stored;
         
         /* The scene now references the textures in the rasterization
          * state record.  Note that now.
          */
         for (i = 0; i < ARRAY_SIZE(setup->fs.current_tex); i++) {
            if (setup->fs.current_tex[i]) {
               if (!lp_scene_add_resource_reference(scene,
                                                    setup->fs.current_tex[i],
                                                    new_scene)) {
                  assert(!new_scene);
                  return FALSE;
               }
            }
         }
      }
   }

   if (setup->dirty & LP_SETUP_NEW_SCISSOR) {
      unsigned i;
      for (i = 0; i < PIPE_MAX_VIEWPORTS; ++i) {
         setup->draw_regions[i] = setup->framebuffer;
         if (setup->scissor_test) {
            u_rect_possible_intersection(&setup->scissors[i],
                                         &setup->draw_regions[i]);
         }
      }
   }

   setup->dirty = 0;

   assert(setup->fs.stored);
   return TRUE;
}
Exemple #3
0
/**
 * Called by vbuf code when we're about to draw something.
 */
static boolean
try_update_scene_state( struct lp_setup_context *setup )
{
   boolean new_scene = (setup->fs.stored == NULL);
   struct lp_scene *scene = setup->scene;
   unsigned i;

   assert(scene);

   if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) {
      uint8_t *stored;
      float* fstored;
      unsigned i, j;
      unsigned size;

      /* Alloc u8_blend_color (16 x i8) and f_blend_color (4 or 8 x f32) */
      size  = 4 * 16 * sizeof(uint8_t);
      size += (LP_MAX_VECTOR_LENGTH / 4) * sizeof(float);
      stored = lp_scene_alloc_aligned(scene, size, LP_MAX_VECTOR_LENGTH);

      if (!stored) {
         assert(!new_scene);
         return FALSE;
      }

      /* Store floating point colour */
      fstored = (float*)(stored + 4*16);
      for (i = 0; i < (LP_MAX_VECTOR_LENGTH / 4); ++i) {
         fstored[i] = setup->blend_color.current.color[i % 4];
      }

      /* smear each blend color component across 16 ubyte elements */
      for (i = 0; i < 4; ++i) {
         uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]);
         for (j = 0; j < 16; ++j)
            stored[i*16 + j] = c;
      }

      setup->blend_color.stored = stored;
      setup->fs.current.jit_context.u8_blend_color = stored;
      setup->fs.current.jit_context.f_blend_color = fstored;
      setup->dirty |= LP_SETUP_NEW_FS;
   }

   if (setup->dirty & LP_SETUP_NEW_CONSTANTS) {
      for (i = 0; i < Elements(setup->constants); ++i) {
         struct pipe_resource *buffer = setup->constants[i].current.buffer;
         const unsigned current_size = setup->constants[i].current.buffer_size;
         const ubyte *current_data = NULL;

         if (buffer) {
            /* resource buffer */
            current_data = (ubyte *) llvmpipe_resource_data(buffer);
         }
         else if (setup->constants[i].current.user_buffer) {
            /* user-space buffer */
            current_data = (ubyte *) setup->constants[i].current.user_buffer;
         }

         if (current_data) {
            current_data += setup->constants[i].current.buffer_offset;

            /* TODO: copy only the actually used constants? */

            if (setup->constants[i].stored_size != current_size ||
               !setup->constants[i].stored_data ||
               memcmp(setup->constants[i].stored_data,
                      current_data,
                      current_size) != 0) {
               void *stored;

               stored = lp_scene_alloc(scene, current_size);
               if (!stored) {
                  assert(!new_scene);
                  return FALSE;
               }

               memcpy(stored,
                      current_data,
                      current_size);
               setup->constants[i].stored_size = current_size;
               setup->constants[i].stored_data = stored;
            }
         }
         else {
            setup->constants[i].stored_size = 0;
            setup->constants[i].stored_data = NULL;
         }

         setup->fs.current.jit_context.constants[i] = setup->constants[i].stored_data;
         setup->dirty |= LP_SETUP_NEW_FS;
      }
   }


   if (setup->dirty & LP_SETUP_NEW_FS) {
      if (!setup->fs.stored ||
          memcmp(setup->fs.stored,
                 &setup->fs.current,
                 sizeof setup->fs.current) != 0)
      {
         struct lp_rast_state *stored;
         
         /* The fs state that's been stored in the scene is different from
          * the new, current state.  So allocate a new lp_rast_state object
          * and append it to the bin's setup data buffer.
          */
         stored = (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored);
         if (!stored) {
            assert(!new_scene);
            return FALSE;
         }

         memcpy(stored,
                &setup->fs.current,
                sizeof setup->fs.current);
         setup->fs.stored = stored;
         
         /* The scene now references the textures in the rasterization
          * state record.  Note that now.
          */
         for (i = 0; i < Elements(setup->fs.current_tex); i++) {
            if (setup->fs.current_tex[i]) {
               if (!lp_scene_add_resource_reference(scene,
                                                    setup->fs.current_tex[i],
                                                    new_scene)) {
                  assert(!new_scene);
                  return FALSE;
               }
            }
         }
      }
   }

   if (setup->dirty & LP_SETUP_NEW_SCISSOR) {
      setup->draw_region = setup->framebuffer;
      if (setup->scissor_test) {
         u_rect_possible_intersection(&setup->scissor,
                                      &setup->draw_region);
      }
   }
                                      
   setup->dirty = 0;

   assert(setup->fs.stored);
   return TRUE;
}