LCOV - code coverage report
Current view: top level - dev/pci/drm/i915 - intel_frontbuffer.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 66 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright © 2014 Intel Corporation
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice (including the next
      12             :  * paragraph) shall be included in all copies or substantial portions of the
      13             :  * Software.
      14             :  *
      15             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      18             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      20             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      21             :  * DEALINGS IN THE SOFTWARE.
      22             :  *
      23             :  * Authors:
      24             :  *      Daniel Vetter <daniel.vetter@ffwll.ch>
      25             :  */
      26             : 
      27             : /**
      28             :  * DOC: frontbuffer tracking
      29             :  *
      30             :  * Many features require us to track changes to the currently active
      31             :  * frontbuffer, especially rendering targeted at the frontbuffer.
      32             :  *
      33             :  * To be able to do so GEM tracks frontbuffers using a bitmask for all possible
      34             :  * frontbuffer slots through i915_gem_track_fb(). The function in this file are
      35             :  * then called when the contents of the frontbuffer are invalidated, when
      36             :  * frontbuffer rendering has stopped again to flush out all the changes and when
      37             :  * the frontbuffer is exchanged with a flip. Subsystems interested in
      38             :  * frontbuffer changes (e.g. PSR, FBC, DRRS) should directly put their callbacks
      39             :  * into the relevant places and filter for the frontbuffer slots that they are
      40             :  * interested int.
      41             :  *
      42             :  * On a high level there are two types of powersaving features. The first one
      43             :  * work like a special cache (FBC and PSR) and are interested when they should
      44             :  * stop caching and when to restart caching. This is done by placing callbacks
      45             :  * into the invalidate and the flush functions: At invalidate the caching must
      46             :  * be stopped and at flush time it can be restarted. And maybe they need to know
      47             :  * when the frontbuffer changes (e.g. when the hw doesn't initiate an invalidate
      48             :  * and flush on its own) which can be achieved with placing callbacks into the
      49             :  * flip functions.
      50             :  *
      51             :  * The other type of display power saving feature only cares about busyness
      52             :  * (e.g. DRRS). In that case all three (invalidate, flush and flip) indicate
      53             :  * busyness. There is no direct way to detect idleness. Instead an idle timer
      54             :  * work delayed work should be started from the flush and flip functions and
      55             :  * cancelled as soon as busyness is detected.
      56             :  *
      57             :  * Note that there's also an older frontbuffer activity tracking scheme which
      58             :  * just tracks general activity. This is done by the various mark_busy and
      59             :  * mark_idle functions. For display power management features using these
      60             :  * functions is deprecated and should be avoided.
      61             :  */
      62             : 
      63             : #include <dev/pci/drm/drmP.h>
      64             : 
      65             : #include "intel_drv.h"
      66             : #include "i915_drv.h"
      67             : 
      68             : /**
      69             :  * intel_fb_obj_invalidate - invalidate frontbuffer object
      70             :  * @obj: GEM object to invalidate
      71             :  * @origin: which operation caused the invalidation
      72             :  *
      73             :  * This function gets called every time rendering on the given object starts and
      74             :  * frontbuffer caching (fbc, low refresh rate for DRRS, panel self refresh) must
      75             :  * be invalidated. For ORIGIN_CS any subsequent invalidation will be delayed
      76             :  * until the rendering completes or a flip on this frontbuffer plane is
      77             :  * scheduled.
      78             :  */
      79           0 : void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
      80             :                              enum fb_op_origin origin)
      81             : {
      82           0 :         struct drm_device *dev = obj->base.dev;
      83           0 :         struct drm_i915_private *dev_priv = to_i915(dev);
      84             : 
      85           0 :         WARN_ON(!mutex_is_locked(&dev->struct_mutex));
      86             : 
      87           0 :         if (!obj->frontbuffer_bits)
      88           0 :                 return;
      89             : 
      90           0 :         if (origin == ORIGIN_CS) {
      91           0 :                 mutex_lock(&dev_priv->fb_tracking.lock);
      92           0 :                 dev_priv->fb_tracking.busy_bits
      93           0 :                         |= obj->frontbuffer_bits;
      94           0 :                 dev_priv->fb_tracking.flip_bits
      95           0 :                         &= ~obj->frontbuffer_bits;
      96           0 :                 mutex_unlock(&dev_priv->fb_tracking.lock);
      97           0 :         }
      98             : 
      99           0 :         intel_psr_invalidate(dev, obj->frontbuffer_bits);
     100           0 :         intel_edp_drrs_invalidate(dev, obj->frontbuffer_bits);
     101           0 :         intel_fbc_invalidate(dev_priv, obj->frontbuffer_bits, origin);
     102           0 : }
     103             : 
     104             : /**
     105             :  * intel_frontbuffer_flush - flush frontbuffer
     106             :  * @dev: DRM device
     107             :  * @frontbuffer_bits: frontbuffer plane tracking bits
     108             :  * @origin: which operation caused the flush
     109             :  *
     110             :  * This function gets called every time rendering on the given planes has
     111             :  * completed and frontbuffer caching can be started again. Flushes will get
     112             :  * delayed if they're blocked by some outstanding asynchronous rendering.
     113             :  *
     114             :  * Can be called without any locks held.
     115             :  */
     116           0 : static void intel_frontbuffer_flush(struct drm_device *dev,
     117             :                                     unsigned frontbuffer_bits,
     118             :                                     enum fb_op_origin origin)
     119             : {
     120           0 :         struct drm_i915_private *dev_priv = to_i915(dev);
     121             : 
     122             :         /* Delay flushing when rings are still busy.*/
     123           0 :         mutex_lock(&dev_priv->fb_tracking.lock);
     124           0 :         frontbuffer_bits &= ~dev_priv->fb_tracking.busy_bits;
     125           0 :         mutex_unlock(&dev_priv->fb_tracking.lock);
     126             : 
     127           0 :         if (!frontbuffer_bits)
     128           0 :                 return;
     129             : 
     130           0 :         intel_edp_drrs_flush(dev, frontbuffer_bits);
     131           0 :         intel_psr_flush(dev, frontbuffer_bits, origin);
     132           0 :         intel_fbc_flush(dev_priv, frontbuffer_bits, origin);
     133           0 : }
     134             : 
     135             : /**
     136             :  * intel_fb_obj_flush - flush frontbuffer object
     137             :  * @obj: GEM object to flush
     138             :  * @retire: set when retiring asynchronous rendering
     139             :  * @origin: which operation caused the flush
     140             :  *
     141             :  * This function gets called every time rendering on the given object has
     142             :  * completed and frontbuffer caching can be started again. If @retire is true
     143             :  * then any delayed flushes will be unblocked.
     144             :  */
     145           0 : void intel_fb_obj_flush(struct drm_i915_gem_object *obj,
     146             :                         bool retire, enum fb_op_origin origin)
     147             : {
     148           0 :         struct drm_device *dev = obj->base.dev;
     149           0 :         struct drm_i915_private *dev_priv = to_i915(dev);
     150             :         unsigned frontbuffer_bits;
     151             : 
     152           0 :         WARN_ON(!mutex_is_locked(&dev->struct_mutex));
     153             : 
     154           0 :         if (!obj->frontbuffer_bits)
     155           0 :                 return;
     156             : 
     157             :         frontbuffer_bits = obj->frontbuffer_bits;
     158             : 
     159           0 :         if (retire) {
     160           0 :                 mutex_lock(&dev_priv->fb_tracking.lock);
     161             :                 /* Filter out new bits since rendering started. */
     162           0 :                 frontbuffer_bits &= dev_priv->fb_tracking.busy_bits;
     163             : 
     164           0 :                 dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits;
     165           0 :                 mutex_unlock(&dev_priv->fb_tracking.lock);
     166           0 :         }
     167             : 
     168           0 :         intel_frontbuffer_flush(dev, frontbuffer_bits, origin);
     169           0 : }
     170             : 
     171             : /**
     172             :  * intel_frontbuffer_flip_prepare - prepare asynchronous frontbuffer flip
     173             :  * @dev: DRM device
     174             :  * @frontbuffer_bits: frontbuffer plane tracking bits
     175             :  *
     176             :  * This function gets called after scheduling a flip on @obj. The actual
     177             :  * frontbuffer flushing will be delayed until completion is signalled with
     178             :  * intel_frontbuffer_flip_complete. If an invalidate happens in between this
     179             :  * flush will be cancelled.
     180             :  *
     181             :  * Can be called without any locks held.
     182             :  */
     183           0 : void intel_frontbuffer_flip_prepare(struct drm_device *dev,
     184             :                                     unsigned frontbuffer_bits)
     185             : {
     186           0 :         struct drm_i915_private *dev_priv = to_i915(dev);
     187             : 
     188           0 :         mutex_lock(&dev_priv->fb_tracking.lock);
     189           0 :         dev_priv->fb_tracking.flip_bits |= frontbuffer_bits;
     190             :         /* Remove stale busy bits due to the old buffer. */
     191           0 :         dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits;
     192           0 :         mutex_unlock(&dev_priv->fb_tracking.lock);
     193             : 
     194           0 :         intel_psr_single_frame_update(dev, frontbuffer_bits);
     195           0 : }
     196             : 
     197             : /**
     198             :  * intel_frontbuffer_flip_complete - complete asynchronous frontbuffer flip
     199             :  * @dev: DRM device
     200             :  * @frontbuffer_bits: frontbuffer plane tracking bits
     201             :  *
     202             :  * This function gets called after the flip has been latched and will complete
     203             :  * on the next vblank. It will execute the flush if it hasn't been cancelled yet.
     204             :  *
     205             :  * Can be called without any locks held.
     206             :  */
     207           0 : void intel_frontbuffer_flip_complete(struct drm_device *dev,
     208             :                                      unsigned frontbuffer_bits)
     209             : {
     210           0 :         struct drm_i915_private *dev_priv = to_i915(dev);
     211             : 
     212           0 :         mutex_lock(&dev_priv->fb_tracking.lock);
     213             :         /* Mask any cancelled flips. */
     214           0 :         frontbuffer_bits &= dev_priv->fb_tracking.flip_bits;
     215           0 :         dev_priv->fb_tracking.flip_bits &= ~frontbuffer_bits;
     216           0 :         mutex_unlock(&dev_priv->fb_tracking.lock);
     217             : 
     218           0 :         intel_frontbuffer_flush(dev, frontbuffer_bits, ORIGIN_FLIP);
     219           0 : }
     220             : 
     221             : /**
     222             :  * intel_frontbuffer_flip - synchronous frontbuffer flip
     223             :  * @dev: DRM device
     224             :  * @frontbuffer_bits: frontbuffer plane tracking bits
     225             :  *
     226             :  * This function gets called after scheduling a flip on @obj. This is for
     227             :  * synchronous plane updates which will happen on the next vblank and which will
     228             :  * not get delayed by pending gpu rendering.
     229             :  *
     230             :  * Can be called without any locks held.
     231             :  */
     232           0 : void intel_frontbuffer_flip(struct drm_device *dev,
     233             :                             unsigned frontbuffer_bits)
     234             : {
     235           0 :         struct drm_i915_private *dev_priv = to_i915(dev);
     236             : 
     237           0 :         mutex_lock(&dev_priv->fb_tracking.lock);
     238             :         /* Remove stale busy bits due to the old buffer. */
     239           0 :         dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits;
     240           0 :         mutex_unlock(&dev_priv->fb_tracking.lock);
     241             : 
     242           0 :         intel_frontbuffer_flush(dev, frontbuffer_bits, ORIGIN_FLIP);
     243           0 : }

Generated by: LCOV version 1.13