diff mbox series

[FFmpeg-devel,v06,2/5] fbtile helperRoutines cpu based framebuffer detiling

Message ID 20200704131717.49428-3-hanishkvc@gmail.com
State New
Headers show
Series KMSGrab, fbtile helpers, hwcontext_drm, hwdownload, fbdetilevf | expand

Checks

Context Check Description
andriy/default pending
andriy/make fail Make failed

Commit Message

hanishkvc July 4, 2020, 1:17 p.m. UTC
Add helper routines which can be used to detile tiled framebuffer
layouts into a linear layout, using the cpu.

Currently it supports Legacy Intel Tile-X, Legacy Intel Tile-Y and
Newer Intel Tile-Yf tiled layouts.

Currently supported pixel format is 32bit RGB.

It also contains detile_generic logic, which can be easily configured
to support different kinds of tiling layouts, at the expense of some
processing speed, compared to developing a targeted detiling logic.
---
 libavutil/Makefile |   2 +
 libavutil/fbtile.c | 441 +++++++++++++++++++++++++++++++++++++++++++++
 libavutil/fbtile.h | 228 +++++++++++++++++++++++
 3 files changed, 671 insertions(+)
 create mode 100644 libavutil/fbtile.c
 create mode 100644 libavutil/fbtile.h

Comments

hanishkvc July 5, 2020, 3:57 a.m. UTC | #1
Hi Lynne,


On Sun, 5 Jul, 2020, 00:53 Lynne, <dev@lynne.ee> wrote:

> Jul 4, 2020, 14:17 by hanishkvc@gmail.com:
>
> > Add helper routines which can be used to detile tiled framebuffer
> > layouts into a linear layout, using the cpu.
> >
> > Currently it supports Legacy Intel Tile-X, Legacy Intel Tile-Y and
> > Newer Intel Tile-Yf tiled layouts.
> >
> > Currently supported pixel format is 32bit RGB.
> >
> > It also contains detile_generic logic, which can be easily configured
> > to support different kinds of tiling layouts, at the expense of some
> > processing speed, compared to developing a targeted detiling logic.
> >
>
> Sorry, but we really cannot afford to have this as part of the public API,
> which it needs to be if it can be used by lavfi. So its unacceptable in its
> current form, especially if all parts dependent on it are compile-time
> options.
> That's why I suggested merging it all into hwcontext_drm.c
>



There is no compile time options which it's users/callers need to
manipulate to use it.

What I meant by easily configurable is, in future if we want to add support
for a new (currently unknown to it) tile layout, there is no need to do it
from scratch. One could just add a new set of boundry conditions with the
required direction changes, and the generic logic can take care of doing
the required tile walking. This is no different than say adding a new
colour format or bit resolution or so to a scaler for example, rather I
would say much simpler than these.

And once the new definition is added into fbtile. It can be used by any of
its users without any additional change.

That's how any library or for that matter any code works currently, so not
sure what's diffrent here that you are objecting to.

Also tile manipulation is a logically independent set of operations which
can be used by any logic and not just hwcontext_drm, and tiling is nothing
unique to hwcontext_drm, so it will be better to keep it independent of
hwcontext_drm, because logically/technically it's independent of it.

Also I seem to be missing something here, what is the technical/... reason
you don't want a frame buffer tile manipulation logic as a public API, in
case if it is?



> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Lynne July 5, 2020, 7:54 a.m. UTC | #2
Jul 5, 2020, 04:57 by hanishkvc@gmail.com:

> Hi Lynne,
>
>
> On Sun, 5 Jul, 2020, 00:53 Lynne, <dev@lynne.ee> wrote:
>
>> Jul 4, 2020, 14:17 by hanishkvc@gmail.com:
>>
>> > Add helper routines which can be used to detile tiled framebuffer
>> > layouts into a linear layout, using the cpu.
>> >
>> > Currently it supports Legacy Intel Tile-X, Legacy Intel Tile-Y and
>> > Newer Intel Tile-Yf tiled layouts.
>> >
>> > Currently supported pixel format is 32bit RGB.
>> >
>> > It also contains detile_generic logic, which can be easily configured
>> > to support different kinds of tiling layouts, at the expense of some
>> > processing speed, compared to developing a targeted detiling logic.
>> >
>>
>> Sorry, but we really cannot afford to have this as part of the public API,
>> which it needs to be if it can be used by lavfi. So its unacceptable in its
>> current form, especially if all parts dependent on it are compile-time
>> options.
>> That's why I suggested merging it all into hwcontext_drm.c
>>
>
>
>
> There is no compile time options which it's users/callers need to
> manipulate to use it.
>
> What I meant by easily configurable is, in future if we want to add support
> for a new (currently unknown to it) tile layout, there is no need to do it
> from scratch. One could just add a new set of boundry conditions with the
> required direction changes, and the generic logic can take care of doing
> the required tile walking. This is no different than say adding a new
> colour format or bit resolution or so to a scaler for example, rather I
> would say much simpler than these.
>
> And once the new definition is added into fbtile. It can be used by any of
> its users without any additional change.
>
> That's how any library or for that matter any code works currently, so not
> sure what's diffrent here that you are objecting to.
>
> Also tile manipulation is a logically independent set of operations which
> can be used by any logic and not just hwcontext_drm, and tiling is nothing
> unique to hwcontext_drm, so it will be better to keep it independent of
> hwcontext_drm, because logically/technically it's independent of it.
>
> Also I seem to be missing something here, what is the technical/... reason
> you don't want a frame buffer tile manipulation logic as a public API, in
> case if it is?
>

Something like this, is like I said, very niche and optionally fixes behavior that shouldn't
ever have been exposed had it not been for the incredibly bad decisions libdrm
made (and we made as well).
And for that, and for not fitting in as any part of any library, I don't want a public API
for this anywhere.

Something like this could belong in libswscale, but that requires not resorting to hacks
and actually implementing tiled pixel formats, which we're definitely not doing.

Hence any patches that actually fix the behavior non-optionally would be what's
accepted.
We're not looking for solutions outside of hwcontext_drm. Like I said, no other API
is that badly designed to give the user access to tiled data. There' no point in having
a generic filter/hwdownload setting because there's nothing other than hwcontext_drm
that would use it properly.

While I'm okay with having the detiling as a separate file, it cannot be exposed via
the public API and any user wishing to detile would have to use the hwcontext API.
And I don't want this as an optional filter either. And no, you can't just duplicate
the tiling code to libavfilter.

Bottom line is, we don't want command-line users to _ever_ see or touch tiled content,
and to do that, you have to make hwcontext_drm.c detile when downloading.
Mark Thompson July 5, 2020, 10:47 p.m. UTC | #3
On 04/07/2020 14:17, hanishkvc wrote:
> Add helper routines which can be used to detile tiled framebuffer
> layouts into a linear layout, using the cpu.
> 
> Currently it supports Legacy Intel Tile-X, Legacy Intel Tile-Y and
> Newer Intel Tile-Yf tiled layouts.
> 
> Currently supported pixel format is 32bit RGB.
> 
> It also contains detile_generic logic, which can be easily configured
> to support different kinds of tiling layouts, at the expense of some
> processing speed, compared to developing a targeted detiling logic.
> ---
>   libavutil/Makefile |   2 +
>   libavutil/fbtile.c | 441 +++++++++++++++++++++++++++++++++++++++++++++
>   libavutil/fbtile.h | 228 +++++++++++++++++++++++
>   3 files changed, 671 insertions(+)
>   create mode 100644 libavutil/fbtile.c
>   create mode 100644 libavutil/fbtile.h

I do think this is a reasonable thing to include in FFmpeg, but please think about what you actually want as a public API here.

Ideally you want to minimise the public API surface while providing something clean and of general use.

So:
- It should probably operate on whole frames - copying pieces of frames or single planes doesn't have any obvious use.
- The pixel format, width, height and pitches will all need to be specified, so AVFrames which already include that information are probably the right structure to use.
- You want to specify a tiling mode for the source frame somehow.
- For the untile case the destination is linear, but a plausible use-case is the opposite so we could include tiling mode for the destination as well.
- The tiling modes will need to be some sort of enum, since they are all ad-hoc setups for particular hardware vendors.
- We can't reuse existing values like those from libdrm because we'd like it to work everywhere it can and there is no intrinsic dependence on libdrm, so it needs to be a new enum.
- Names for the tiling modes should be valid everywhere, so if they are platform-dependent (like Intel X/Y tiling) then the platform will need to be included in the name.
- Linear should be in the tiling mode enum, so that you don't need special cases elsewhere.
- All the dispatch between different implementations can happen internally, so it doesn't need to be exposed.
- Not everything will actually be implemented, so it will need to be able to return an error indicating that a particular case is not available.

Given that, I make the desired public API to be exactly one enum and one function.  It would look something like:

enum AVTilingMode {
   AV_TILING_MODE_LINEAR = 0,
   AV_TILING_MODE_INTEL_GEN7_X,
   AV_TILING_MODE_INTEL_GEN7_Y,
   AV_TILING_MODE_INTEL_GEN9_X,
   AV_TILING_MODE_INTEL_GEN9_Y,
   AV_TILING_MODE_INTEL_YF,
};

int av_frame_copy_with_tiling(const AVFrame *dst, enum AVTilingMode dst_tiling,
                               const AVFrame *src, enum AVTilingMode src_tiling);


Some other thoughts:
- Functions should all be static unless you are intentionally exposing them as public API.
- Libraries must not include mutable globals.
- Note that av_log(NULL, ...) should never be called from a library unless you really are in a global context.  I think you probably just don't want to include any user-facing logging at all.
- Look at the coding style guide, especially around naming and operator spacing.

Thanks,

- Mark
Lynne July 5, 2020, 11:30 p.m. UTC | #4
Jul 5, 2020, 23:47 by sw@jkqxz.net:

> On 04/07/2020 14:17, hanishkvc wrote:
>
>> Add helper routines which can be used to detile tiled framebuffer
>> layouts into a linear layout, using the cpu.
>>
>> Currently it supports Legacy Intel Tile-X, Legacy Intel Tile-Y and
>> Newer Intel Tile-Yf tiled layouts.
>>
>> Currently supported pixel format is 32bit RGB.
>>
>> It also contains detile_generic logic, which can be easily configured
>> to support different kinds of tiling layouts, at the expense of some
>> processing speed, compared to developing a targeted detiling logic.
>> ---
>>  libavutil/Makefile |   2 +
>>  libavutil/fbtile.c | 441 +++++++++++++++++++++++++++++++++++++++++++++
>>  libavutil/fbtile.h | 228 +++++++++++++++++++++++
>>  3 files changed, 671 insertions(+)
>>  create mode 100644 libavutil/fbtile.c
>>  create mode 100644 libavutil/fbtile.h
>>
>
> I do think this is a reasonable thing to include in FFmpeg, but please think about what you actually want as a public API here.
>
> Ideally you want to minimise the public API surface while providing something clean and of general use.
>
> So:
> - It should probably operate on whole frames - copying pieces of frames or single planes doesn't have any obvious use.
> - The pixel format, width, height and pitches will all need to be specified, so AVFrames which already include that information are probably the right structure to use.
> - You want to specify a tiling mode for the source frame somehow.
> - For the untile case the destination is linear, but a plausible use-case is the opposite so we could include tiling mode for the destination as well.
> - The tiling modes will need to be some sort of enum, since they are all ad-hoc setups for particular hardware vendors.
> - We can't reuse existing values like those from libdrm because we'd like it to work everywhere it can and there is no intrinsic dependence on libdrm, so it needs to be a new enum.
> - Names for the tiling modes should be valid everywhere, so if they are platform-dependent (like Intel X/Y tiling) then the platform will need to be included in the name.
> - Linear should be in the tiling mode enum, so that you don't need special cases elsewhere.
> - All the dispatch between different implementations can happen internally, so it doesn't need to be exposed.
> - Not everything will actually be implemented, so it will need to be able to return an error indicating that a particular case is not available.
>
> Given that, I make the desired public API to be exactly one enum and one function.  It would look something like:
>
> enum AVTilingMode {
>  AV_TILING_MODE_LINEAR = 0,
>  AV_TILING_MODE_INTEL_GEN7_X,
>  AV_TILING_MODE_INTEL_GEN7_Y,
>  AV_TILING_MODE_INTEL_GEN9_X,
>  AV_TILING_MODE_INTEL_GEN9_Y,
>  AV_TILING_MODE_INTEL_YF,
> };
>
> int av_frame_copy_with_tiling(const AVFrame *dst, enum AVTilingMode dst_tiling,
>  const AVFrame *src, enum AVTilingMode src_tiling);
>
>
> Some other thoughts:
> - Functions should all be static unless you are intentionally exposing them as public API.
> - Libraries must not include mutable globals.
> - Note that av_log(NULL, ...) should never be called from a library unless you really are in a global context.  I think you probably just don't want to include any user-facing logging at all.
> - Look at the coding style guide, especially around naming and operator spacing.
>

Yes, in general those are good guidelines for public APIs.
But please, _don't_ in this case. Really. I've already said its not a good idea and I'll reject
future patches that do simply because its a problem exclusive to hwcontext_drm and directly
solvable there.
Mark Thompson July 6, 2020, 10:13 p.m. UTC | #5
On 06/07/2020 00:30, Lynne wrote:
> Jul 5, 2020, 23:47 by sw@jkqxz.net:
> 
>> On 04/07/2020 14:17, hanishkvc wrote:
>>
>>> Add helper routines which can be used to detile tiled framebuffer
>>> layouts into a linear layout, using the cpu.
>>>
>>> Currently it supports Legacy Intel Tile-X, Legacy Intel Tile-Y and
>>> Newer Intel Tile-Yf tiled layouts.
>>>
>>> Currently supported pixel format is 32bit RGB.
>>>
>>> It also contains detile_generic logic, which can be easily configured
>>> to support different kinds of tiling layouts, at the expense of some
>>> processing speed, compared to developing a targeted detiling logic.
>>> ---
>>>   libavutil/Makefile |   2 +
>>>   libavutil/fbtile.c | 441 +++++++++++++++++++++++++++++++++++++++++++++
>>>   libavutil/fbtile.h | 228 +++++++++++++++++++++++
>>>   3 files changed, 671 insertions(+)
>>>   create mode 100644 libavutil/fbtile.c
>>>   create mode 100644 libavutil/fbtile.h
>>>
>>
>> I do think this is a reasonable thing to include in FFmpeg, but please think about what you actually want as a public API here.
>>
>> Ideally you want to minimise the public API surface while providing something clean and of general use.
>>
>> So:
>> - It should probably operate on whole frames - copying pieces of frames or single planes doesn't have any obvious use.
>> - The pixel format, width, height and pitches will all need to be specified, so AVFrames which already include that information are probably the right structure to use.
>> - You want to specify a tiling mode for the source frame somehow.
>> - For the untile case the destination is linear, but a plausible use-case is the opposite so we could include tiling mode for the destination as well.
>> - The tiling modes will need to be some sort of enum, since they are all ad-hoc setups for particular hardware vendors.
>> - We can't reuse existing values like those from libdrm because we'd like it to work everywhere it can and there is no intrinsic dependence on libdrm, so it needs to be a new enum.
>> - Names for the tiling modes should be valid everywhere, so if they are platform-dependent (like Intel X/Y tiling) then the platform will need to be included in the name.
>> - Linear should be in the tiling mode enum, so that you don't need special cases elsewhere.
>> - All the dispatch between different implementations can happen internally, so it doesn't need to be exposed.
>> - Not everything will actually be implemented, so it will need to be able to return an error indicating that a particular case is not available.
>>
>> Given that, I make the desired public API to be exactly one enum and one function.  It would look something like:
>>
>> enum AVTilingMode {
>>   AV_TILING_MODE_LINEAR = 0,
>>   AV_TILING_MODE_INTEL_GEN7_X,
>>   AV_TILING_MODE_INTEL_GEN7_Y,
>>   AV_TILING_MODE_INTEL_GEN9_X,
>>   AV_TILING_MODE_INTEL_GEN9_Y,
>>   AV_TILING_MODE_INTEL_YF,
>> };
>>
>> int av_frame_copy_with_tiling(const AVFrame *dst, enum AVTilingMode dst_tiling,
>>   const AVFrame *src, enum AVTilingMode src_tiling);
>>
>>
>> Some other thoughts:
>> - Functions should all be static unless you are intentionally exposing them as public API.
>> - Libraries must not include mutable globals.
>> - Note that av_log(NULL, ...) should never be called from a library unless you really are in a global context.  I think you probably just don't want to include any user-facing logging at all.
>> - Look at the coding style guide, especially around naming and operator spacing.
>>
> 
> Yes, in general those are good guidelines for public APIs.
> But please, _don't_ in this case. Really. I've already said its not a good idea and I'll reject
> future patches that do simply because its a problem exclusive to hwcontext_drm and directly
> solvable there.

Yeah, that's fair - there isn't really any good reason to make it public unless there is another use-case entirely independent from the DRM one.

- Mark
hanishkvc July 11, 2020, 3:49 p.m. UTC | #6
Hi Mark,

On Mon, Jul 6, 2020 at 4:18 AM Mark Thompson <sw@jkqxz.net> wrote:

> On 04/07/2020 14:17, hanishkvc wrote:
> > Add helper routines which can be used to detile tiled framebuffer
> > layouts into a linear layout, using the cpu.
> >
> > Currently it supports Legacy Intel Tile-X, Legacy Intel Tile-Y and
> > Newer Intel Tile-Yf tiled layouts.
> >
> > Currently supported pixel format is 32bit RGB.
> >
> > It also contains detile_generic logic, which can be easily configured
> > to support different kinds of tiling layouts, at the expense of some
> > processing speed, compared to developing a targeted detiling logic.
> > ---
> >   libavutil/Makefile |   2 +
> >   libavutil/fbtile.c | 441 +++++++++++++++++++++++++++++++++++++++++++++
> >   libavutil/fbtile.h | 228 +++++++++++++++++++++++
> >   3 files changed, 671 insertions(+)
> >   create mode 100644 libavutil/fbtile.c
> >   create mode 100644 libavutil/fbtile.h
>
> I do think this is a reasonable thing to include in FFmpeg, but please
> think about what you actually want as a public API here.
>
> Ideally you want to minimise the public API surface while providing
> something clean and of general use.
>
> So:
> - It should probably operate on whole frames - copying pieces of frames or
> single planes doesn't have any obvious use.
> - The pixel format, width, height and pitches will all need to be
> specified, so AVFrames which already include that information are probably
> the right structure to use.
> - You want to specify a tiling mode for the source frame somehow.
> - For the untile case the destination is linear, but a plausible use-case
> is the opposite so we could include tiling mode for the destination as well.
> - The tiling modes will need to be some sort of enum, since they are all
> ad-hoc setups for particular hardware vendors.
> - We can't reuse existing values like those from libdrm because we'd like
> it to work everywhere it can and there is no intrinsic dependence on
> libdrm, so it needs to be a new enum.
> - Names for the tiling modes should be valid everywhere, so if they are
> platform-dependent (like Intel X/Y tiling) then the platform will need to
> be included in the name.
> - Linear should be in the tiling mode enum, so that you don't need special
> cases elsewhere.
> - All the dispatch between different implementations can happen
> internally, so it doesn't need to be exposed.
> - Not everything will actually be implemented, so it will need to be able
> to return an error indicating that a particular case is not available.
>
> Given that, I make the desired public API to be exactly one enum and one
> function.  It would look something like:
>
> enum AVTilingMode {
>    AV_TILING_MODE_LINEAR = 0,
>    AV_TILING_MODE_INTEL_GEN7_X,
>    AV_TILING_MODE_INTEL_GEN7_Y,
>    AV_TILING_MODE_INTEL_GEN9_X,
>    AV_TILING_MODE_INTEL_GEN9_Y,
>    AV_TILING_MODE_INTEL_YF,
> };
>
> int av_frame_copy_with_tiling(const AVFrame *dst, enum AVTilingMode
> dst_tiling,
>                                const AVFrame *src, enum AVTilingMode
> src_tiling);
>
>
> Some other thoughts:
> - Functions should all be static unless you are intentionally exposing
> them as public API.
> - Libraries must not include mutable globals.
> - Note that av_log(NULL, ...) should never be called from a library unless
> you really are in a global context.  I think you probably just don't want
> to include any user-facing logging at all.
> - Look at the coding style guide, especially around naming and operator
> spacing.
>
>
Thanks for the feedback. I thought your suggestion about
av_frame_copy_with_tiling was good. However as you and Lynne seem to have
discussed further and concluded not to expose a public api like
av_frame_copy_with_tiling, so the equivalent function which I had, which
has been further updated to support tiling also (in addition to detiling,
so that is a more fuller copy), I have named as fbtile_frame_copy (it is
limited to the 3 common Intel tile formats, the logic is extendable in a
easy way for new tile layouts) in my new patch.

In future if ffmpeg is implementing such an api, you may also want to add
an additional status argument, which will indicate as to whether the logic
did only a plain copy or a tile/detile based copy. As the user of the
function may want indication as to whether the tiling related operation was
done or not (may not be done, because the combination of
pixelformat+planes+tile layout involved may not be supported). At the same
time still retaining the simple 0 for success (a fall back plain copy can
still be a valid copy at one level) function return value.

Also you may require two additional public api

one) which maps from a hardware(and related) context specific tile layout
id to the tile layout id used by the ffmpeg avframe tile support logic.

two) which tells whether the combination of pixel format (+ planes) + tile
layout is supported or not.

Just for my understanding, if a library wants to log something, so that it
doesnt chain back corner case and or debug meta data to its users, what
should it do. Should it define a dummy class with a name field or some such
thing (NOTE: I havent really looked at av_log in detail, this is just a
guess based on some comment or so, which I vaguely remember reading related
to av_log or some other thing).


> Thanks,
>
> - Mark
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
diff mbox series

Patch

diff --git a/libavutil/Makefile b/libavutil/Makefile
index 9b08372eb2..9b58ac5980 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -84,6 +84,7 @@  HEADERS = adler32.h                                                     \
           xtea.h                                                        \
           tea.h                                                         \
           tx.h                                                          \
+          fbtile.h                                                      \
 
 HEADERS-$(CONFIG_LZO)                   += lzo.h
 
@@ -169,6 +170,7 @@  OBJS = adler32.o                                                        \
        tx_float.o                                                       \
        tx_double.o                                                      \
        tx_int32.o                                                       \
+       fbtile.o                                                         \
        video_enc_params.o                                               \
 
 
diff --git a/libavutil/fbtile.c b/libavutil/fbtile.c
new file mode 100644
index 0000000000..ca04f0a7d2
--- /dev/null
+++ b/libavutil/fbtile.c
@@ -0,0 +1,441 @@ 
+/*
+ * CPU based Framebuffer Tile DeTile logic
+ * Copyright (c) 2020 C Hanish Menon <HanishKVC>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "avutil.h"
+#include "common.h"
+#include "fbtile.h"
+#if CONFIG_LIBDRM
+#include <drm_fourcc.h>
+#endif
+
+
+int fbtilemode_from_formatmodifier(uint64_t formatModifier)
+{
+    int mode = TILE_NONE_END;
+
+#if CONFIG_LIBDRM
+    switch(formatModifier) {
+        case DRM_FORMAT_MOD_LINEAR:
+            mode = TILE_NONE;
+            break;
+        case I915_FORMAT_MOD_X_TILED:
+            mode = TILE_INTELX;
+            break;
+        case I915_FORMAT_MOD_Y_TILED:
+            mode = TILE_INTELY;
+            break;
+        case I915_FORMAT_MOD_Yf_TILED:
+            mode = TILE_INTELYF;
+            break;
+        default:
+            mode = TILE_NONE_END;
+            break;
+    }
+#endif
+#ifdef DEBUG_FBTILE_FORMATMODIFIER_MAPPING
+    av_log(NULL, AV_LOG_DEBUG, "fbtile:formatmodifier[%lx] mapped to mode[%d]\n", formatModifier, mode);
+#endif
+    return mode;
+}
+
+
+/**
+ * Supported pixel formats
+ * Currently only RGB based 32bit formats are specified
+ * TODO: Technically the logic is transparent to 16bit RGB formats also to a great extent
+ */
+const enum AVPixelFormat fbtilePixFormats[] = {AV_PIX_FMT_RGB0, AV_PIX_FMT_0RGB, AV_PIX_FMT_BGR0, AV_PIX_FMT_0BGR,
+                                               AV_PIX_FMT_RGBA, AV_PIX_FMT_ARGB, AV_PIX_FMT_BGRA, AV_PIX_FMT_ABGR,
+                                               AV_PIX_FMT_NONE};
+
+int fbtile_checkpixformats(const enum AVPixelFormat srcPixFormat, const enum AVPixelFormat dstPixFormat)
+{
+    int okSrc = 0;
+    int okDst = 0;
+    for (int i = 0; fbtilePixFormats[i] != AV_PIX_FMT_NONE; i++) {
+        if (fbtilePixFormats[i] == srcPixFormat)
+            okSrc = 1;
+        if (fbtilePixFormats[i] == dstPixFormat)
+            okDst = 1;
+    }
+    return (okSrc && okDst);
+}
+
+
+void detile_intelx(int w, int h,
+                          uint8_t *dst, int dstLineSize,
+                          const uint8_t *src, int srcLineSize)
+{
+    // Offsets and LineSize are in bytes
+    const int pixBytes = 4;                     // bytes per pixel
+    const int tileW = 128;                      // tileWidth inPixels, 512/4, For a 32Bits/Pixel framebuffer
+    const int tileH = 8;                        // tileHeight inPixelLines
+    const int tileWBytes = tileW*pixBytes;      // tileWidth inBytes
+
+    if (w*pixBytes != srcLineSize) {
+        av_log(NULL, AV_LOG_ERROR, "fbdetile:intelx: w%dxh%d, dL%d, sL%d\n", w, h, dstLineSize, srcLineSize);
+        av_log(NULL, AV_LOG_ERROR, "fbdetile:intelx: dont support LineSize | Pitch going beyond width\n");
+    }
+    int sO = 0;                 // srcOffset inBytes
+    int dX = 0;                 // destX inPixels
+    int dY = 0;                 // destY inPixels
+    int nTLines = (w*h)/tileW;  // numTileLines; One TileLine = One TileWidth
+    int cTL = 0;                // curTileLine
+    while (cTL < nTLines) {
+        int dO = dY*dstLineSize + dX*pixBytes;
+#ifdef DEBUG_FBTILE
+        av_log(NULL, AV_LOG_DEBUG, "fbdetile:intelx: dX%d dY%d, sO%d, dO%d\n", dX, dY, sO, dO);
+#endif
+        memcpy(dst+dO+0*dstLineSize, src+sO+0*tileWBytes, tileWBytes);
+        memcpy(dst+dO+1*dstLineSize, src+sO+1*tileWBytes, tileWBytes);
+        memcpy(dst+dO+2*dstLineSize, src+sO+2*tileWBytes, tileWBytes);
+        memcpy(dst+dO+3*dstLineSize, src+sO+3*tileWBytes, tileWBytes);
+        memcpy(dst+dO+4*dstLineSize, src+sO+4*tileWBytes, tileWBytes);
+        memcpy(dst+dO+5*dstLineSize, src+sO+5*tileWBytes, tileWBytes);
+        memcpy(dst+dO+6*dstLineSize, src+sO+6*tileWBytes, tileWBytes);
+        memcpy(dst+dO+7*dstLineSize, src+sO+7*tileWBytes, tileWBytes);
+        dX += tileW;
+        if (dX >= w) {
+            dX = 0;
+            dY += tileH;
+        }
+        sO = sO + tileW*tileH*pixBytes;
+        cTL += tileH;
+    }
+}
+
+
+/*
+ * Intel Legacy Tile-Y layout conversion support
+ *
+ * currently done in a simple dumb way. Two low hanging optimisations
+ * that could be readily applied are
+ *
+ * a) unrolling the inner for loop
+ *    --- Given small size memcpy, should help, DONE
+ *
+ * b) using simd based 128bit loading and storing along with prefetch
+ *    hinting.
+ *
+ *    TOTHINK|CHECK: Does memcpy already does this and more if situation
+ *    is right?!
+ *
+ *    As code (or even intrinsics) would be specific to each architecture,
+ *    avoiding for now. Later have to check if vector_size attribute and
+ *    corresponding implementation by gcc can handle different architectures
+ *    properly, such that it wont become worse than memcpy provided for that
+ *    architecture.
+ *
+ * Or maybe I could even merge the two intel detiling logics into one, as
+ * the semantic and flow is almost same for both logics.
+ *
+ */
+void detile_intely(int w, int h,
+                          uint8_t *dst, int dstLineSize,
+                          const uint8_t *src, int srcLineSize)
+{
+    // Offsets and LineSize are in bytes
+    const int pixBytes = 4;                 // bytesPerPixel
+    // tileW represents subTileWidth here, as it can be repeated to fill a tile
+    const int tileW = 4;                    // tileWidth inPixels, 16/4, For a 32Bits/Pixel framebuffer
+    const int tileH = 32;                   // tileHeight inPixelLines
+    const int tileWBytes = tileW*pixBytes;  // tileWidth inBytes
+
+    if (w*pixBytes != srcLineSize) {
+        av_log(NULL, AV_LOG_ERROR, "fbdetile:intely: w%dxh%d, dL%d, sL%d\n", w, h, dstLineSize, srcLineSize);
+        av_log(NULL, AV_LOG_ERROR, "fbdetile:intely: dont support LineSize | Pitch going beyond width\n");
+    }
+    int sO = 0;
+    int dX = 0;
+    int dY = 0;
+    const int nTLines = (w*h)/tileW;
+    int cTL = 0;
+    while (cTL < nTLines) {
+        int dO = dY*dstLineSize + dX*pixBytes;
+#ifdef DEBUG_FBTILE
+        av_log(NULL, AV_LOG_DEBUG, "fbdetile:intely: dX%d dY%d, sO%d, dO%d\n", dX, dY, sO, dO);
+#endif
+
+        memcpy(dst+dO+0*dstLineSize, src+sO+0*tileWBytes, tileWBytes);
+        memcpy(dst+dO+1*dstLineSize, src+sO+1*tileWBytes, tileWBytes);
+        memcpy(dst+dO+2*dstLineSize, src+sO+2*tileWBytes, tileWBytes);
+        memcpy(dst+dO+3*dstLineSize, src+sO+3*tileWBytes, tileWBytes);
+        memcpy(dst+dO+4*dstLineSize, src+sO+4*tileWBytes, tileWBytes);
+        memcpy(dst+dO+5*dstLineSize, src+sO+5*tileWBytes, tileWBytes);
+        memcpy(dst+dO+6*dstLineSize, src+sO+6*tileWBytes, tileWBytes);
+        memcpy(dst+dO+7*dstLineSize, src+sO+7*tileWBytes, tileWBytes);
+        memcpy(dst+dO+8*dstLineSize, src+sO+8*tileWBytes, tileWBytes);
+        memcpy(dst+dO+9*dstLineSize, src+sO+9*tileWBytes, tileWBytes);
+        memcpy(dst+dO+10*dstLineSize, src+sO+10*tileWBytes, tileWBytes);
+        memcpy(dst+dO+11*dstLineSize, src+sO+11*tileWBytes, tileWBytes);
+        memcpy(dst+dO+12*dstLineSize, src+sO+12*tileWBytes, tileWBytes);
+        memcpy(dst+dO+13*dstLineSize, src+sO+13*tileWBytes, tileWBytes);
+        memcpy(dst+dO+14*dstLineSize, src+sO+14*tileWBytes, tileWBytes);
+        memcpy(dst+dO+15*dstLineSize, src+sO+15*tileWBytes, tileWBytes);
+        memcpy(dst+dO+16*dstLineSize, src+sO+16*tileWBytes, tileWBytes);
+        memcpy(dst+dO+17*dstLineSize, src+sO+17*tileWBytes, tileWBytes);
+        memcpy(dst+dO+18*dstLineSize, src+sO+18*tileWBytes, tileWBytes);
+        memcpy(dst+dO+19*dstLineSize, src+sO+19*tileWBytes, tileWBytes);
+        memcpy(dst+dO+20*dstLineSize, src+sO+20*tileWBytes, tileWBytes);
+        memcpy(dst+dO+21*dstLineSize, src+sO+21*tileWBytes, tileWBytes);
+        memcpy(dst+dO+22*dstLineSize, src+sO+22*tileWBytes, tileWBytes);
+        memcpy(dst+dO+23*dstLineSize, src+sO+23*tileWBytes, tileWBytes);
+        memcpy(dst+dO+24*dstLineSize, src+sO+24*tileWBytes, tileWBytes);
+        memcpy(dst+dO+25*dstLineSize, src+sO+25*tileWBytes, tileWBytes);
+        memcpy(dst+dO+26*dstLineSize, src+sO+26*tileWBytes, tileWBytes);
+        memcpy(dst+dO+27*dstLineSize, src+sO+27*tileWBytes, tileWBytes);
+        memcpy(dst+dO+28*dstLineSize, src+sO+28*tileWBytes, tileWBytes);
+        memcpy(dst+dO+29*dstLineSize, src+sO+29*tileWBytes, tileWBytes);
+        memcpy(dst+dO+30*dstLineSize, src+sO+30*tileWBytes, tileWBytes);
+        memcpy(dst+dO+31*dstLineSize, src+sO+31*tileWBytes, tileWBytes);
+
+        dX += tileW;
+        if (dX >= w) {
+            dX = 0;
+            dY += tileH;
+        }
+        sO = sO + tileW*tileH*pixBytes;
+        cTL += tileH;
+    }
+}
+
+
+/*
+ * Generic detile logic
+ */
+
+/*
+ * Direction Change Entry
+ * Used to specify the tile walking of subtiles within a tile.
+ */
+/**
+ * Settings for Intel Tile-Yf framebuffer layout.
+ * May need to swap the 4 pixel wide subtile, have to check doc bit more
+ */
+const int tyfBytesPerPixel = 4;
+const int tyfSubTileWidth = 4;
+const int tyfSubTileHeight = 8;
+const int tyfSubTileWidthBytes = tyfSubTileWidth*tyfBytesPerPixel; //16
+const int tyfTileWidth = 32;
+const int tyfTileHeight = 32;
+const int tyfNumDirChanges = 6;
+struct dirChange tyfDirChanges[] = { {8, 4, 0}, {16, -4, 8}, {32, 4, -8}, {64, -12, 8 }, {128, 4, -24}, {256, 4, -24} };
+
+/**
+ * Setting for Intel Tile-X framebuffer layout
+ */
+const int txBytesPerPixel = 4;
+const int txSubTileWidth = 128;
+const int txSubTileHeight = 8;
+const int txSubTileWidthBytes = txSubTileWidth*txBytesPerPixel; //512
+const int txTileWidth = 128;
+const int txTileHeight = 8;
+const int txNumDirChanges = 1;
+struct dirChange txDirChanges[] = { {8, 128, 0} };
+
+/**
+ * Setting for Intel Tile-Y framebuffer layout
+ * Even thou a simple generic detiling logic doesnt require the
+ * dummy 256 posOffset entry. The pseudo parallel detiling based
+ * opti logic requires to know about the Tile boundry.
+ */
+const int tyBytesPerPixel = 4;
+const int tySubTileWidth = 4;
+const int tySubTileHeight = 32;
+const int tySubTileWidthBytes = tySubTileWidth*tyBytesPerPixel; //16
+const int tyTileWidth = 32;
+const int tyTileHeight = 32;
+const int tyNumDirChanges = 2;
+struct dirChange tyDirChanges[] = { {32, 4, 0}, {256, 4, 0} };
+
+
+void detile_generic_simple(int w, int h,
+                                  uint8_t *dst, int dstLineSize,
+                                  const uint8_t *src, int srcLineSize,
+                                  int bytesPerPixel,
+                                  int subTileWidth, int subTileHeight, int subTileWidthBytes,
+                                  int tileWidth, int tileHeight,
+                                  int numDirChanges, struct dirChange *dirChanges)
+{
+
+    if (w*bytesPerPixel != srcLineSize) {
+        av_log(NULL, AV_LOG_ERROR, "fbdetile:generic: w%dxh%d, dL%d, sL%d\n", w, h, dstLineSize, srcLineSize);
+        av_log(NULL, AV_LOG_ERROR, "fbdetile:generic: dont support LineSize | Pitch going beyond width\n");
+    }
+    int sO = 0;
+    int dX = 0;
+    int dY = 0;
+    int nSTLines = (w*h)/subTileWidth;  // numSubTileLines
+    int cSTL = 0;                       // curSubTileLine
+    while (cSTL < nSTLines) {
+        int dO = dY*dstLineSize + dX*bytesPerPixel;
+#ifdef DEBUG_FBTILE
+        av_log(NULL, AV_LOG_DEBUG, "fbdetile:generic: dX%d dY%d, sO%d, dO%d\n", dX, dY, sO, dO);
+#endif
+
+        for (int k = 0; k < subTileHeight; k++) {
+            memcpy(dst+dO+k*dstLineSize, src+sO+k*subTileWidthBytes, subTileWidthBytes);
+        }
+        sO = sO + subTileHeight*subTileWidthBytes;
+
+        cSTL += subTileHeight;
+        for (int i=numDirChanges-1; i>=0; i--) {
+            if ((cSTL%dirChanges[i].posOffset) == 0) {
+                dX += dirChanges[i].xDelta;
+                dY += dirChanges[i].yDelta;
+                break;
+            }
+        }
+        if (dX >= w) {
+            dX = 0;
+            dY += tileHeight;
+        }
+    }
+}
+
+
+void detile_generic_opti(int w, int h,
+                                uint8_t *dst, int dstLineSize,
+                                const uint8_t *src, int srcLineSize,
+                                int bytesPerPixel,
+                                int subTileWidth, int subTileHeight, int subTileWidthBytes,
+                                int tileWidth, int tileHeight,
+                                int numDirChanges, struct dirChange *dirChanges)
+{
+    int parallel = 1;
+
+    if (w*bytesPerPixel != srcLineSize) {
+        av_log(NULL, AV_LOG_ERROR, "fbdetile:generic: w%dxh%d, dL%d, sL%d\n", w, h, dstLineSize, srcLineSize);
+        av_log(NULL, AV_LOG_ERROR, "fbdetile:generic: dont support LineSize | Pitch going beyond width\n");
+    }
+    if (w%tileWidth != 0) {
+        av_log(NULL, AV_LOG_ERROR, "fbdetile:generic:NotSupported:NonMultWidth: width%d, tileWidth%d\n", w, tileWidth);
+    }
+    int sO = 0;
+    int sOPrev = 0;
+    int dX = 0;
+    int dY = 0;
+    int nSTLines = (w*h)/subTileWidth;
+    //int nSTLinesInATile = (tileWidth*tileHeight)/subTileWidth;
+    int nTilesInARow = w/tileWidth;
+    for (parallel=8; parallel>0; parallel--) {
+        if (nTilesInARow%parallel == 0)
+            break;
+    }
+    int cSTL = 0;
+    int curTileInRow = 0;
+    while (cSTL < nSTLines) {
+        int dO = dY*dstLineSize + dX*bytesPerPixel;
+#ifdef DEBUG_FBTILE
+        av_log(NULL, AV_LOG_DEBUG, "fbdetile:generic: dX%d dY%d, sO%d, dO%d\n", dX, dY, sO, dO);
+#endif
+
+        // As most tiling layouts have a minimum subtile of 4x4, if I remember correctly,
+        // so this loop has been unrolled to be multiples of 4, and speed up a bit.
+        // However tiling involving 3x3 or 2x2 wont be handlable. Use detile_generic_simple
+        // for such tile layouts.
+        // Detile parallely to a limited extent. To avoid any cache set-associativity and or
+        // limited cache based thrashing, keep it spacially and inturn temporaly small at one level.
+        for (int k = 0; k < subTileHeight; k+=4) {
+            for (int p = 0; p < parallel; p++) {
+                int pSrcOffset = p*tileWidth*tileHeight*bytesPerPixel;
+                int pDstOffset = p*tileWidth*bytesPerPixel;
+                memcpy(dst+dO+k*dstLineSize+pDstOffset, src+sO+k*subTileWidthBytes+pSrcOffset, subTileWidthBytes);
+                memcpy(dst+dO+(k+1)*dstLineSize+pDstOffset, src+sO+(k+1)*subTileWidthBytes+pSrcOffset, subTileWidthBytes);
+                memcpy(dst+dO+(k+2)*dstLineSize+pDstOffset, src+sO+(k+2)*subTileWidthBytes+pSrcOffset, subTileWidthBytes);
+                memcpy(dst+dO+(k+3)*dstLineSize+pDstOffset, src+sO+(k+3)*subTileWidthBytes+pSrcOffset, subTileWidthBytes);
+            }
+        }
+        sO = sO + subTileHeight*subTileWidthBytes;
+
+        cSTL += subTileHeight;
+        for (int i=numDirChanges-1; i>=0; i--) {
+            if ((cSTL%dirChanges[i].posOffset) == 0) {
+                if (i == numDirChanges-1) {
+                    curTileInRow += parallel;
+                    dX = curTileInRow*tileWidth;
+                    sO = sOPrev + tileWidth*tileHeight*bytesPerPixel*(parallel);
+                    sOPrev = sO;
+                } else {
+                    dX += dirChanges[i].xDelta;
+                }
+                dY += dirChanges[i].yDelta;
+		break;
+            }
+        }
+        if (dX >= w) {
+            dX = 0;
+            curTileInRow = 0;
+            dY += tileHeight;
+            if (dY >= h) {
+                break;
+            }
+        }
+    }
+}
+
+
+int detile_this(int mode, uint64_t arg1,
+                        int w, int h,
+                        uint8_t *dst, int dstLineSize,
+                        uint8_t *src, int srcLineSize,
+                        int bytesPerPixel)
+{
+    static int logState=0;
+    if (mode == TILE_AUTO) {
+        mode = fbtilemode_from_formatmodifier(arg1);
+    }
+    if (mode == TILE_NONE) {
+        return 1;
+    }
+
+    if (mode == TILE_INTELX) {
+        detile_intelx(w, h, dst, dstLineSize, src, srcLineSize);
+    } else if (mode == TILE_INTELY) {
+        detile_intely(w, h, dst, dstLineSize, src, srcLineSize);
+    } else if (mode == TILE_INTELYF) {
+        detile_generic(w, h, dst, dstLineSize, src, srcLineSize,
+                            tyfBytesPerPixel, tyfSubTileWidth, tyfSubTileHeight, tyfSubTileWidthBytes,
+                            tyfTileWidth, tyfTileHeight,
+                            tyfNumDirChanges, tyfDirChanges);
+    } else if (mode == TILE_INTELGX) {
+        detile_generic(w, h, dst, dstLineSize, src, srcLineSize,
+                            txBytesPerPixel, txSubTileWidth, txSubTileHeight, txSubTileWidthBytes,
+                            txTileWidth, txTileHeight,
+                            txNumDirChanges, txDirChanges);
+    } else if (mode == TILE_INTELGY) {
+        detile_generic(w, h, dst, dstLineSize, src, srcLineSize,
+                            tyBytesPerPixel, tySubTileWidth, tySubTileHeight, tySubTileWidthBytes,
+                            tyTileWidth, tyTileHeight,
+                            tyNumDirChanges, tyDirChanges);
+    } else if (mode == TILE_NONE_END) {
+        av_log_once(NULL, AV_LOG_WARNING, AV_LOG_VERBOSE, &logState, "fbtile:detile_this:TILE_AUTOOr???: invalid or unsupported format_modifier:%"PRIx64"\n",arg1);
+        return 1;
+    } else {
+        av_log(NULL, AV_LOG_ERROR, "fbtile:detile_this:????: unknown mode specified, check caller\n");
+        return 1;
+    }
+    return 0;
+}
+
+
+// vim: set expandtab sts=4: //
diff --git a/libavutil/fbtile.h b/libavutil/fbtile.h
new file mode 100644
index 0000000000..51556db93a
--- /dev/null
+++ b/libavutil/fbtile.h
@@ -0,0 +1,228 @@ 
+/*
+ * CPU based Framebuffer Tile DeTile logic
+ * Copyright (c) 2020 C Hanish Menon <HanishKVC>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_FBTILE_H
+#define AVUTIL_FBTILE_H
+
+#include <stdio.h>
+#include <stdint.h>
+
+/**
+ * @file
+ * @brief CPU based Framebuffer tiler detiler
+ * @author C Hanish Menon <HanishKVC>
+ * @{
+ */
+
+
+enum FBTileMode {
+    TILE_NONE,
+    TILE_AUTO,
+    TILE_INTELX,
+    TILE_INTELY,
+    TILE_INTELYF,
+    TILE_INTELGX,
+    TILE_INTELGY,
+    TILE_NONE_END,
+};
+
+
+/**
+ * Map from formatmodifier to fbtile's internal mode.
+ *
+ * @param formatModifier the format_modifier to map
+ * @return the fbtile's equivalent internal mode
+ */
+#undef DEBUG_FBTILE_FORMATMODIFIER_MAPPING
+int fbtilemode_from_formatmodifier(uint64_t formatModifier);
+
+
+/**
+ * Supported pixel formats by the fbtile logics
+ */
+extern const enum AVPixelFormat fbtilePixFormats[];
+/**
+ * Check if the given pixel formats are supported by fbtile logic.
+ *
+ * @param srcPixFormat pixel format of source image
+ * @param dstPixFormat pixel format of destination image
+ */
+int fbtile_checkpixformats(const enum AVPixelFormat srcPixFormat, const enum AVPixelFormat dstPixFormat);
+
+
+/**
+ * Detile legacy intel tile-x layout into linear layout.
+ *
+ * @param w width of the image
+ * @param h height of the image
+ * @param dst the destination image buffer
+ * @param dstLineSize the size of each row in dst image, in bytes
+ * @param src the source image buffer
+ * @param srcLineSize the size of each row in src image, in bytes
+ */
+void detile_intelx(int w, int h,
+                          uint8_t *dst, int dstLineSize,
+                          const uint8_t *src, int srcLineSize);
+
+
+/**
+ * Detile legacy intel tile-y layout into linear layout.
+ *
+ * @param w width of the image
+ * @param h height of the image
+ * @param dst the destination image buffer
+ * @param dstLineSize the size of each row in dst image, in bytes
+ * @param src the source image buffer
+ * @param srcLineSize the size of each row in src image, in bytes
+ */
+void detile_intely(int w, int h,
+                          uint8_t *dst, int dstLineSize,
+                          const uint8_t *src, int srcLineSize);
+
+
+/**
+ * Generic Logic.
+ */
+
+/*
+ * Direction Change Entry
+ * Used to specify the tile walking of subtiles within a tile.
+ */
+struct dirChange {
+    int posOffset;
+    int xDelta;
+    int yDelta;
+};
+/**
+ * Settings for Intel Tile-Yf framebuffer layout.
+ * May need to swap the 4 pixel wide subtile, have to check doc bit more
+ */
+extern const int tyfBytesPerPixel;
+extern const int tyfSubTileWidth;
+extern const int tyfSubTileHeight;
+extern const int tyfSubTileWidthBytes;
+extern const int tyfTileWidth;
+extern const int tyfTileHeight;
+extern const int tyfNumDirChanges;
+extern struct dirChange tyfDirChanges[];
+/**
+ * Setting for Intel Tile-X framebuffer layout
+ */
+extern const int txBytesPerPixel;
+extern const int txSubTileWidth;
+extern const int txSubTileHeight;
+extern const int txSubTileWidthBytes;
+extern const int txTileWidth;
+extern const int txTileHeight;
+extern const int txNumDirChanges;
+extern struct dirChange txDirChanges[];
+/**
+ * Setting for Intel Tile-Y framebuffer layout
+ * Even thou a simple generic detiling logic doesnt require the
+ * dummy 256 posOffset entry. The pseudo parallel detiling based
+ * opti logic requires to know about the Tile boundry.
+ */
+extern const int tyBytesPerPixel;
+extern const int tySubTileWidth;
+extern const int tySubTileHeight;
+extern const int tySubTileWidthBytes;
+extern const int tyTileWidth;
+extern const int tyTileHeight;
+extern const int tyNumDirChanges;
+extern struct dirChange tyDirChanges[];
+
+/**
+ * Generic Logic to Detile into linear layout.
+ *
+ * @param w width of the image
+ * @param h height of the image
+ * @param dst the destination image buffer
+ * @param dstLineSize the size of each row in dst image, in bytes
+ * @param src the source image buffer
+ * @param srcLineSize the size of each row in src image, in bytes
+ * @param bytesPerPixel the bytes per pixel for the image
+ * @param subTileWidth the width of subtile within the tile, in pixels
+ * @param subTileHeight the height of subtile within the tile, in pixels
+ * @param subTileWidthBytes the width of subtile within the tile, in bytes
+ * @param tileWidth the width of the tile, in pixels
+ * @param tileHeight the height of the tile, in pixels
+ */
+
+
+/**
+ * Generic detile simple version, which is fine-grained.
+ */
+void detile_generic_simple(int w, int h,
+                                  uint8_t *dst, int dstLineSize,
+                                  const uint8_t *src, int srcLineSize,
+                                  int bytesPerPixel,
+                                  int subTileWidth, int subTileHeight, int subTileWidthBytes,
+                                  int tileWidth, int tileHeight,
+                                  int numDirChanges, struct dirChange *dirChanges);
+
+
+/**
+ * Generic detile optimised version, minimum subtile supported 4x4.
+ */
+void detile_generic_opti(int w, int h,
+                                uint8_t *dst, int dstLineSize,
+                                const uint8_t *src, int srcLineSize,
+                                int bytesPerPixel,
+                                int subTileWidth, int subTileHeight, int subTileWidthBytes,
+                                int tileWidth, int tileHeight,
+                                int numDirChanges, struct dirChange *dirChanges);
+
+
+#ifdef DETILE_GENERIC_OPTI
+#define detile_generic detile_generic_opti
+#else
+#define detile_generic detile_generic_simple
+#endif
+
+
+/**
+ * detile demuxer.
+ *
+ * @param mode the fbtile mode based detiling to call
+ * @param arg1 the format_modifier, in case mode is TILE_AUTO
+ * @param w width of the image
+ * @param h height of the image
+ * @param dst the destination image buffer
+ * @param dstLineSize the size of each row in dst image, in bytes
+ * @param src the source image buffer
+ * @param srcLineSize the size of each row in src image, in bytes
+ * @param bytesPerPixel the bytes per pixel for the image
+ *
+ * @return 0 if detiled, 1 if not
+ */
+int detile_this(int mode, uint64_t arg1,
+                        int w, int h,
+                        uint8_t *dst, int dstLineSize,
+                        uint8_t *src, int srcLineSize,
+                        int bytesPerPixel);
+
+
+/**
+ * @}
+ */
+
+#endif /* AVUTIL_FBTILE_H */
+// vim: set expandtab sts=4: //