3737#include "util/u_format.h"
3838#include "util/u_math.h"
3939#include "util/u_memory.h"
40+ #include "util/u_rect.h"
4041
4142#include "i915_context.h"
4243#include "i915_resource.h"
@@ -710,7 +711,7 @@ i915_texture_destroy(struct pipe_screen *screen,
710711 FREE (tex );
711712}
712713
713- static struct pipe_transfer *
714+ static struct pipe_transfer *
714715i915_texture_get_transfer (struct pipe_context * pipe ,
715716 struct pipe_resource * resource ,
716717 unsigned level ,
@@ -719,71 +720,211 @@ i915_texture_get_transfer(struct pipe_context *pipe,
719720{
720721 struct i915_context * i915 = i915_context (pipe );
721722 struct i915_texture * tex = i915_texture (resource );
722- struct pipe_transfer * transfer = util_slab_alloc (& i915 -> transfer_pool );
723+ struct i915_transfer * transfer = util_slab_alloc (& i915 -> texture_transfer_pool );
724+ boolean use_staging_texture = FALSE;
723725
724726 if (transfer == NULL )
725727 return NULL ;
726728
727- transfer -> resource = resource ;
728- transfer -> level = level ;
729- transfer -> usage = usage ;
730- transfer -> box = * box ;
731- transfer -> stride = tex -> stride ;
732- /* FIXME: layer_stride */
729+ transfer -> b .resource = resource ;
730+ transfer -> b .level = level ;
731+ transfer -> b .usage = usage ;
732+ transfer -> b .box = * box ;
733+ transfer -> b .stride = tex -> stride ;
734+ transfer -> staging_texture = NULL ;
735+ /* XXX: handle depth textures everyhwere*/
736+ transfer -> b .layer_stride = 0 ;
737+ transfer -> b .data = NULL ;
738+
739+ /* only support textures we can render to, because we need that for u_blitter */
740+ if (i915 -> blitter &&
741+ i915_is_format_supported (NULL , /* screen */
742+ transfer -> b .resource -> format ,
743+ 0 , /* target */
744+ 1 , /* sample count */
745+ PIPE_BIND_RENDER_TARGET ) &&
746+ (usage & PIPE_TRANSFER_WRITE ) &&
747+ !(usage & (PIPE_TRANSFER_READ | PIPE_TRANSFER_DONTBLOCK | PIPE_TRANSFER_UNSYNCHRONIZED )))
748+ use_staging_texture = TRUE;
749+
750+ use_staging_texture = FALSE;
751+
752+ if (use_staging_texture ) {
753+ /*
754+ * Allocate the untiled staging texture.
755+ * If the alloc fails, transfer->staging_texture is NULL and we fallback to a map()
756+ */
757+ transfer -> staging_texture = i915_texture_create (pipe -> screen , resource , TRUE);
758+ }
733759
734- return transfer ;
760+ return ( struct pipe_transfer * ) transfer ;
735761}
736762
737763static void
738764i915_transfer_destroy (struct pipe_context * pipe ,
739765 struct pipe_transfer * transfer )
740766{
741767 struct i915_context * i915 = i915_context (pipe );
742- util_slab_free (& i915 -> transfer_pool , transfer );
768+ struct i915_transfer * itransfer = (struct i915_transfer * )transfer ;
769+
770+ if ((itransfer -> staging_texture ) &&
771+ (transfer -> usage & PIPE_TRANSFER_WRITE )) {
772+ struct pipe_box sbox ;
773+
774+ u_box_origin_2d (itransfer -> b .box .width , itransfer -> b .box .height , & sbox );
775+ pipe -> resource_copy_region (pipe , itransfer -> b .resource , itransfer -> b .level ,
776+ itransfer -> b .box .x , itransfer -> b .box .y , itransfer -> b .box .z ,
777+ itransfer -> staging_texture ,
778+ 0 , & sbox );
779+ pipe -> flush (pipe , NULL );
780+ pipe_resource_reference (& itransfer -> staging_texture , NULL );
781+ }
782+
783+ util_slab_free (& i915 -> texture_transfer_pool , itransfer );
743784}
744785
745786static void *
746787i915_texture_transfer_map (struct pipe_context * pipe ,
747788 struct pipe_transfer * transfer )
748789{
749- struct pipe_resource * resource = transfer -> resource ;
750- struct i915_texture * tex = i915_texture (resource );
790+ struct i915_transfer * itransfer = (struct i915_transfer * )transfer ;
791+ struct pipe_resource * resource = itransfer -> b .resource ;
792+ struct i915_texture * tex = NULL ;
751793 struct i915_winsys * iws = i915_screen (pipe -> screen )-> iws ;
752- struct pipe_box * box = & transfer -> box ;
794+ struct pipe_box * box = & itransfer -> b . box ;
753795 enum pipe_format format = resource -> format ;
754796 unsigned offset ;
755797 char * map ;
756798
757799 if (resource -> target != PIPE_TEXTURE_3D &&
758800 resource -> target != PIPE_TEXTURE_CUBE )
759801 assert (box -> z == 0 );
760- offset = i915_texture_offset (tex , transfer -> level , box -> z );
761802
762- /* TODO this is a sledgehammer */
763- pipe -> flush (pipe , NULL );
803+ if (itransfer -> staging_texture ) {
804+ tex = i915_texture (itransfer -> staging_texture );
805+ } else {
806+ /* TODO this is a sledgehammer */
807+ tex = i915_texture (resource );
808+ pipe -> flush (pipe , NULL );
809+ }
810+
811+ offset = i915_texture_offset (tex , itransfer -> b .level , box -> z );
764812
765813 map = iws -> buffer_map (iws , tex -> buffer ,
766- (transfer -> usage & PIPE_TRANSFER_WRITE ) ? TRUE : FALSE);
767- if (map == NULL )
814+ (itransfer -> b . usage & PIPE_TRANSFER_WRITE ) ? TRUE : FALSE);
815+ if (map == NULL ) {
768816 return NULL ;
817+ }
769818
770819 return map + offset +
771- box -> y / util_format_get_blockheight (format ) * transfer -> stride +
820+ box -> y / util_format_get_blockheight (format ) * itransfer -> b . stride +
772821 box -> x / util_format_get_blockwidth (format ) * util_format_get_blocksize (format );
773822}
774823
775824static void
776825i915_texture_transfer_unmap (struct pipe_context * pipe ,
777826 struct pipe_transfer * transfer )
778827{
779- struct i915_texture * tex = i915_texture (transfer -> resource );
828+ struct i915_transfer * itransfer = (struct i915_transfer * )transfer ;
829+ struct i915_texture * tex = i915_texture (itransfer -> b .resource );
780830 struct i915_winsys * iws = i915_screen (tex -> b .b .screen )-> iws ;
831+
832+ if (itransfer -> staging_texture )
833+ tex = i915_texture (itransfer -> staging_texture );
834+
781835 iws -> buffer_unmap (iws , tex -> buffer );
782836}
783837
838+ static void i915_transfer_inline_write ( struct pipe_context * pipe ,
839+ struct pipe_resource * resource ,
840+ unsigned level ,
841+ unsigned usage ,
842+ const struct pipe_box * box ,
843+ const void * data ,
844+ unsigned stride ,
845+ unsigned layer_stride )
846+ {
847+ struct pipe_transfer * transfer = NULL ;
848+ struct i915_transfer * itransfer = NULL ;
849+ const uint8_t * src_data = data ;
850+ unsigned i ;
851+
852+ transfer = pipe -> get_transfer (pipe ,
853+ resource ,
854+ level ,
855+ usage ,
856+ box );
857+ if (transfer == NULL )
858+ goto out ;
859+
860+ itransfer = (struct i915_transfer * )transfer ;
861+
862+ if (itransfer -> staging_texture ) {
863+ struct i915_texture * tex = i915_texture (itransfer -> staging_texture );
864+ enum pipe_format format = tex -> b .b .format ;
865+ struct i915_winsys * iws = i915_screen (tex -> b .b .screen )-> iws ;
866+ size_t offset ;
867+ size_t size ;
868+
869+ offset = i915_texture_offset (tex , transfer -> level , transfer -> box .z );
870+
871+ for (i = 0 ; i < box -> depth ; i ++ ) {
872+ if (!tex -> b .b .last_level &&
873+ tex -> b .b .width0 == transfer -> box .width ) {
874+ unsigned nby = util_format_get_nblocksy (format , transfer -> box .y );
875+ assert (!offset );
876+ assert (!transfer -> box .x );
877+ assert (tex -> stride == transfer -> stride );
878+
879+ offset += tex -> stride * nby ;
880+ size = util_format_get_2d_size (format , transfer -> stride ,
881+ transfer -> box .height );
882+ iws -> buffer_write (iws , tex -> buffer , offset , size , transfer -> data );
883+
884+ } else {
885+ unsigned nby = util_format_get_nblocksy (format , transfer -> box .y );
886+ int i ;
887+ offset += util_format_get_stride (format , transfer -> box .x );
888+ size = transfer -> stride ;
889+
890+ for (i = 0 ; i < nby ; i ++ ) {
891+ iws -> buffer_write (iws , tex -> buffer , offset , size , transfer -> data );
892+ offset += tex -> stride ;
893+ }
894+ }
895+ offset += layer_stride ;
896+ }
897+ } else {
898+ uint8_t * map = pipe_transfer_map (pipe , & itransfer -> b );
899+ if (map == NULL )
900+ goto nomap ;
901+
902+ for (i = 0 ; i < box -> depth ; i ++ ) {
903+ util_copy_rect (map ,
904+ resource -> format ,
905+ itransfer -> b .stride , /* bytes */
906+ 0 , 0 ,
907+ box -> width ,
908+ box -> height ,
909+ src_data ,
910+ stride , /* bytes */
911+ 0 , 0 );
912+ map += itransfer -> b .layer_stride ;
913+ src_data += layer_stride ;
914+ }
915+ nomap :
916+ if (map )
917+ pipe_transfer_unmap (pipe , & itransfer -> b );
918+ }
919+
920+ out :
921+ if (itransfer )
922+ pipe_transfer_destroy (pipe , & itransfer -> b );
923+ }
924+
784925
785926
786- struct u_resource_vtbl i915_texture_vtbl =
927+ struct u_resource_vtbl i915_texture_vtbl =
787928{
788929 i915_texture_get_handle , /* get_handle */
789930 i915_texture_destroy , /* resource_destroy */
@@ -792,15 +933,16 @@ struct u_resource_vtbl i915_texture_vtbl =
792933 i915_texture_transfer_map , /* transfer_map */
793934 u_default_transfer_flush_region , /* transfer_flush_region */
794935 i915_texture_transfer_unmap , /* transfer_unmap */
795- u_default_transfer_inline_write /* transfer_inline_write */
936+ i915_transfer_inline_write /* transfer_inline_write */
796937};
797938
798939
799940
800941
801942struct pipe_resource *
802943i915_texture_create (struct pipe_screen * screen ,
803- const struct pipe_resource * template )
944+ const struct pipe_resource * template ,
945+ boolean force_untiled )
804946{
805947 struct i915_screen * is = i915_screen (screen );
806948 struct i915_winsys * iws = is -> iws ;
@@ -815,7 +957,10 @@ i915_texture_create(struct pipe_screen *screen,
815957 pipe_reference_init (& tex -> b .b .reference , 1 );
816958 tex -> b .b .screen = screen ;
817959
818- tex -> tiling = i915_texture_tiling (is , tex );
960+ if (force_untiled )
961+ tex -> tiling = I915_TILE_NONE ;
962+ else
963+ tex -> tiling = i915_texture_tiling (is , tex );
819964
820965 if (is -> is_i945 ) {
821966 if (!i945_texture_layout (tex ))
@@ -835,8 +980,12 @@ i915_texture_create(struct pipe_screen *screen,
835980 else
836981 buf_usage = I915_NEW_TEXTURE ;
837982
838- tex -> buffer = iws -> buffer_create_tiled (iws , & tex -> stride , tex -> total_nblocksy ,
839- & tex -> tiling , buf_usage );
983+ if (tex -> tiling == I915_TILE_NONE )
984+ tex -> buffer = iws -> buffer_create (iws , tex -> total_nblocksy * tex -> stride ,
985+ buf_usage );
986+ else
987+ tex -> buffer = iws -> buffer_create_tiled (iws , & tex -> stride , tex -> total_nblocksy ,
988+ & tex -> tiling , buf_usage );
840989 if (!tex -> buffer )
841990 goto fail ;
842991
0 commit comments