2014-05-14 17:02:16 +03:00
/*
* Copyright © 2014 Intel Corporation
*
* 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 ( including the next
* paragraph ) 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 :
* Mika Kuoppala < mika . kuoppala @ intel . com >
*
*/
# include "i915_drv.h"
# include "intel_renderstate.h"
2014-06-10 11:23:33 +01:00
struct render_state {
const struct intel_renderstate_rodata * rodata ;
2014-05-14 17:02:16 +03:00
struct drm_i915_gem_object * obj ;
2014-06-10 11:23:33 +01:00
u64 ggtt_offset ;
int gen ;
2014-05-14 17:02:16 +03:00
} ;
static const struct intel_renderstate_rodata *
render_state_get_rodata ( struct drm_device * dev , const int gen )
{
switch ( gen ) {
case 6 :
return & gen6_null_state ;
case 7 :
return & gen7_null_state ;
case 8 :
return & gen8_null_state ;
}
return NULL ;
}
2014-06-10 11:23:33 +01:00
static int render_state_init ( struct render_state * so , struct drm_device * dev )
2014-05-14 17:02:16 +03:00
{
int ret ;
2014-06-10 11:23:33 +01:00
so - > gen = INTEL_INFO ( dev ) - > gen ;
so - > rodata = render_state_get_rodata ( dev , so - > gen ) ;
if ( so - > rodata = = NULL )
return 0 ;
if ( so - > rodata - > batch_items * 4 > 4096 )
2014-05-14 17:02:16 +03:00
return - EINVAL ;
2014-06-10 11:23:33 +01:00
so - > obj = i915_gem_alloc_object ( dev , 4096 ) ;
if ( so - > obj = = NULL )
return - ENOMEM ;
ret = i915_gem_obj_ggtt_pin ( so - > obj , 4096 , 0 ) ;
if ( ret )
goto free_gem ;
so - > ggtt_offset = i915_gem_obj_ggtt_offset ( so - > obj ) ;
return 0 ;
free_gem :
drm_gem_object_unreference ( & so - > obj - > base ) ;
return ret ;
}
static int render_state_setup ( struct render_state * so )
{
const struct intel_renderstate_rodata * rodata = so - > rodata ;
unsigned int i = 0 , reloc_index = 0 ;
struct page * page ;
u32 * d ;
int ret ;
2014-05-14 17:02:16 +03:00
ret = i915_gem_object_set_to_cpu_domain ( so - > obj , true ) ;
if ( ret )
return ret ;
2014-06-10 11:23:33 +01:00
page = sg_page ( so - > obj - > pages - > sgl ) ;
d = kmap ( page ) ;
2014-05-14 17:02:16 +03:00
while ( i < rodata - > batch_items ) {
u32 s = rodata - > batch [ i ] ;
2014-06-10 11:23:33 +01:00
if ( i * 4 = = rodata - > reloc [ reloc_index ] ) {
u64 r = s + so - > ggtt_offset ;
s = lower_32_bits ( r ) ;
if ( so - > gen > = 8 ) {
2014-05-14 17:02:16 +03:00
if ( i + 1 > = rodata - > batch_items | |
rodata - > batch [ i + 1 ] ! = 0 )
return - EINVAL ;
2014-06-10 11:23:33 +01:00
d [ i + + ] = s ;
s = upper_32_bits ( r ) ;
2014-05-14 17:02:16 +03:00
}
reloc_index + + ;
}
2014-06-10 11:23:33 +01:00
d [ i + + ] = s ;
2014-05-14 17:02:16 +03:00
}
2014-06-10 11:23:33 +01:00
kunmap ( page ) ;
2014-05-14 17:02:16 +03:00
ret = i915_gem_object_set_to_gtt_domain ( so - > obj , false ) ;
if ( ret )
return ret ;
2014-06-10 11:23:33 +01:00
if ( rodata - > reloc [ reloc_index ] ! = - 1 ) {
DRM_ERROR ( " only %d relocs resolved \n " , reloc_index ) ;
2014-05-14 17:02:16 +03:00
return - EINVAL ;
}
return 0 ;
}
2014-06-10 11:23:33 +01:00
static void render_state_fini ( struct render_state * so )
{
i915_gem_object_ggtt_unpin ( so - > obj ) ;
drm_gem_object_unreference ( & so - > obj - > base ) ;
}
2014-05-22 14:13:33 +01:00
int i915_gem_render_state_init ( struct intel_engine_cs * ring )
2014-05-14 17:02:16 +03:00
{
2014-06-10 11:23:33 +01:00
struct render_state so ;
2014-05-14 17:02:16 +03:00
int ret ;
2014-05-21 19:01:06 +03:00
if ( WARN_ON ( ring - > id ! = RCS ) )
return - ENOENT ;
2014-06-10 11:23:33 +01:00
ret = render_state_init ( & so , ring - > dev ) ;
if ( ret )
return ret ;
2014-05-14 17:02:16 +03:00
2014-06-10 11:23:33 +01:00
if ( so . rodata = = NULL )
return 0 ;
2014-05-14 17:02:16 +03:00
2014-06-10 11:23:33 +01:00
ret = render_state_setup ( & so ) ;
2014-05-14 17:02:16 +03:00
if ( ret )
goto out ;
ret = ring - > dispatch_execbuffer ( ring ,
2014-06-10 11:23:33 +01:00
so . ggtt_offset ,
so . rodata - > batch_items * 4 ,
2014-05-14 17:02:16 +03:00
I915_DISPATCH_SECURE ) ;
if ( ret )
goto out ;
2014-06-10 11:23:33 +01:00
i915_vma_move_to_active ( i915_gem_obj_to_ggtt ( so . obj ) , ring ) ;
2014-05-14 17:02:16 +03:00
2014-06-10 11:23:33 +01:00
ret = __i915_add_request ( ring , NULL , so . obj , NULL ) ;
2014-05-21 19:01:06 +03:00
/* __i915_add_request moves object to inactive if it fails */
2014-05-14 17:02:16 +03:00
out :
2014-06-10 11:23:33 +01:00
render_state_fini ( & so ) ;
2014-05-14 17:02:16 +03:00
return ret ;
}